Memory variables, IO mapping and ROM analysys are from "Inside Commodore DOS" book by Richard Immers, Ph.D. and Gerald G. Neufeld, Ph.D. published in 1984. The book is available on Internet Archive. Tables below have only minor typo corrections.
ROM table uses following DOS version for ROM disassembly:
Binaries of other versions of DOS ROM are also available on zimmers.net. Differences between versions are summarized in the archive. Amazing mist64 github repo has "ready to build" source code for different versions of Commodore DOS for 1540, 1541, 1541C and 1541-II drives.
ROM disassembly and tables digitization made by g3sl@protonmail.ch. Feel free to send me you comments suggestions and fixes.
2021-11-06 Fix function headers, minor typos fixes.
2021-10-27 Initial document.
Job queue: $0000-$0005The job queue is used to tell the disk controller what disk operations to perform. A disk command such as LOAD, SAVE, SCRATCH, etc. is interpreted by the drive's 6502 (while in its normal mode) and broken down into a set of simple operations (jobs) such as: read track 9 sector 18 into data buffer #2, write the data in buffer #3 out to track 12 sector 5, etc. The track and sector information required for the job is placed into the header table and the JOB CODE corresponding to the job to be done is put in the job queue. The job code's position in the queue indicates which data buffer (if any) is to be used and where the track and sector information is stored in the header table. When the 6502 is next in its floppy disk controller mode (it switches every 10 milliseconds), it scans the job queue looking for jobs to do. If it finds one, it carries it out making use of the track and sector information in the header table. Once the job is done, or aborted, the disk controller replaces the job code with an error code that indicates the job status.
|
||
JOBS | 0000 | Use buffer #0 ($0300+), find T/S in $06/7 |
0001 | Use buffer #1 ($0400+), find T/S in $08/9 |
|
0002 | Use buffer #2 ($0500+), find T/S in $0A/B |
|
0003 | Use buffer #3 ($0600+), find T/S in $0C/D |
|
0004 | Use buffer #4 ($0700+), find T/S in $0E/F |
|
0005 | Use buffer #5 (no RAM), find T/S in $10/1 |
|
Header table: $0006-$0011This is the area that specifies which tracks and sectors are to be used for the jobs in the job queue. Tracks and sectors are not needed for BUMP or JUMP jobs. |
||
HDRS | 0006 | Track/sector for job in $0000 (buffer 0) |
0008 | Track/sector for job in $0001 (buffer 1) |
|
000A | Track/sector for job in $0002 (buffer 2) |
|
000C | Track/sector for job in $0003 (buffer 3) |
|
000E | Track/sector for job in $0004 (buffer 4) |
|
0010 | Track/sector for job in $0005 (buffer 5) |
|
DSKID | 0012 | Master copy of disk ID. This is the ID specified when the disk was formatted. It is updated whenever a SEEK job is performed (see ROM patch $EF25) . The initialize command performs a seek and therefore updates the master ID.
|
0014 | Unused - Disk ID for drive #1 |
|
HEADER | 0016 | Image of the most recent header read. The characters appear here in the same sequence that Commodore's manual says they are recorded onto the disk surface,
|
ACTJOB | 001B | Not used |
WPSW | 001C | Flag to indicate that there has been a change in the write protect status. |
001D | Unused (WPSW for drive #1) |
|
LWPT | 001E | Last state of the write protect switch |
001F | UNUSED (LWPT for drive #1) Set to $01 on power-up |
|
DRVST | 0020 | Disk drive status
|
0021 | Unused (DRVST for drive #1) |
|
DRVTRK | 0022 | Track currently under R/W head |
0023 | Unused (DRVTRK for drive #1) |
|
STAB | 0024 | Work area for doing interconversions of binary data and its GCR write images. |
SAVPNT | 002E | Temporary storage of pointers |
BUFPNT | 0030 | Pointer to currently active buffer |
HDRPNT | 0032 | Pointer to active values in header table |
GCRPNT | 0034 | Pointer to last character converted |
GCRERR | 0035 | Not used |
BYTCNT | 0036 | Byte counter for GCR/binary conversions |
BITCNT | 0037 | Not used |
BID | 0038 | Data block ID character ($07) |
HBID | 0039 | Header block ID character ($08) |
CHKSUM | 003A | Storage of data or header checksum |
HINIB | 003B | Unused |
BYTE | 003C | Unused |
DRIVE | 003D | Always $00 on 1541 |
CDRIVE | 003E | Currently active drive ($FF if inactive) |
JOBN | 003F | Position of last job in job queue (0-5) |
TRACC | 0040 | Byte counter for GCR/binary conversions |
NXTJOB | 0041 | Position of next job in job queue (0-5) |
NXTRK | 0042 | Next track to move head to |
SECTR | 0043 | Sector counter. Used by format routine |
WORK | 0044 | Temporary workspace |
JOB | 0045 | Temporary storage of job code |
CTRACK | 0046 | Unused |
DBID | 0047 | Data block ID code. Set on reset to $07. This may be changed to write or read data blocks with different data block ID codes. However, the first nybble of the data block ID code should always be a zero ($0-). Otherwise, the controller will have difficulty detecting the end of the sync mark and the start of DBID. If you try to read a sector whose DBID is different from the value stored here, the disk controller will put an error code of $04 in the job queue and the drive will report a #22 error (DATA BLOCK NOT FOUND) . |
ACLTIM | 0048 | Timer for acceleration of head |
SAVSP | 0049 | Temporary save of the stack pointer |
STEPS | 004A | The number of steps to move the head to get to the desired track. To move the head over 1 track, requires XX steps. Values between and 127 move the head out (to lower track numbers) . Values over 128 move the head (256-value) steps in (to higher track numbers) |
TMP | 004B | Temporary storage |
CSECT | 004C | Last sector read |
NEXTS | 004D | Next sector to service |
NXTBF | 004E | Hi byte of a pointer to the next buffer of GCR bytes to be changed into binary. The GCR bytes in the overflow buffer are translated first. This points to the buffer that holds the rest of them. |
NXTPNT | 004F | Lo byte of a pointer to the next GCR byte location that is to be translated |
GCRFLG | 0050 | Flag to indicate whether the data in the currently active buffer has been left in binary (0) or GCR (1) form. |
FTNUM | 0051 | Used by the formatting routine to store the number of the track currently being formatted. Set on reset to $FF. |
BTAB | 0052 | Staging area for the four binary bytes being converted to GCR by PUT4BG ($F6D0) or from GCR by GET4GB ($F7E6) . |
GTAB | 0056 | Staging area for the five GCR bytes being converted from binary by PUT4BG ($F6D0) or to binary by GET4GB ($F7E6) . |
AS | 005E | Number of steps to use to accelerate or decelerate when stepping the head ($04) |
AF | 005F | Acceleration/deceleration factor ($04) |
ACLSTP | 0060 | Number of steps left to accelerate or decelerate when stepping the head |
RSTEPS | 0061 | Number of steps left to step the head in fast stepping (run) mode. |
NXTST | 0062 | Pointer to the appropriate head stepping routine. Normally $FA05 (not stepping) |
MINSTP | 0064 | Minimum number of steps for the head to move to make the use of fast stepping mode useful ($C8). If fewer steps needed, use the slow stepping mode. |
VNMI | 0065 | Pointer to start of NMI routine ($EB2E) . Set on power up or drive reset. |
NMIFLG | 0067 | Flag to indicate whether NMI in progress |
AUTOFG | 0068 | Flag to enable (0) or disable (1) the auto initialization of a disk (read BAM) if ID mismatch detected. |
SECINC | 0069 | Sector increment for use by SEQ routine. Set on reset to ($0A) . |
REVCNT | 006A | Counter for error recovery (number of attempts so far) Set on reset to $05 |
USRJMP | 006B | Pointer to the start of the user jump table ($FFF6) . Set on power up or reset. |
BMPNT | 006D | Pointer to the start of the bit map ($0400). Set when a disk is initialized. |
T0 | 006F | Temporary work area ($6F on reset) |
T1 | 0070 | Temporary work area |
T2 | 0071 | Temporary work area |
T3 | 0072 | Temporary work area ($FF on reset) |
T4 | 0073 | Temporary work area |
0074 | Temporary work area |
|
IP | 0075 | Indirect pointer variable ($0100) Set on power up or reset. |
LSNADR | 0077 | Listener address ($28 on reset) |
TLKADR | 0078 | Talker address ($48 on reset) |
LSNACT | 0079 | Active listener flag |
TLKACT | 007A | Active talker flag |
ADRSED | 007B | Addressed flag |
ATNPND | 007C | Attention pending flag |
ATNMOD | 007D | 6502 in attention mode |
PRGTRK | 007E | Last program accessed |
DRVNUM | 007F | Current drive number (always in 1541) |
TRACK | 0080 | Current track number ($00 after use) |
SECTOR | 0081 | Current sector number ($00 after use) |
LINDX | 0082 | Logical index (current channel#) |
SA | 0083 | Current secondary address |
ORGSA | 0084 | Original secondary address |
DATA | 0085 | Temporary data byte |
R0 | 0086 | Temporary result |
R1 | 0087 | Temporary result |
R2 | 0088 | Temporary result |
R3 | 0089 | Temporary result |
R4 | 008A | Temporary result |
RESULT | 008B | Result area ($008B-$008E) |
ACCUM | 008F | Accumulator ($008F-0093) |
DIRBUF | 0094 | Directory buffer ($0094-0095) $05/$02 |
ICMD | 0096 | IEEE command in (not used on 1541) |
MYPA | 0097 | MY PA flag $00 |
CONT | 0098 | Bit counter for serial $00 |
Buffer byte pointersThese pointers (one for each buffer) are used to point at the next byte in the buffer to be used. The B-P command sets these pointers. |
||
BUFTAB | 0099 | Points to next byte in buffer #0 ($0300) |
009B | Points to next byte in buffer #1 ($0400) |
|
009D | Points to next byte in buffer #2 ($0500) |
|
009F | Points to next byte in buffer #3 ($0600) |
|
00A1 | Points to next byte in buffer #4 ($0700) |
|
00A3 | Points to next byte in CMD buffer ($0200) |
|
00A5 | Points to next byte in ERR buf f er ($02D6 ) |
|
BUF0 | 00A7 | Table of channel#'s assigned to each of the buffers. $FF is inactive buffer. |
BUF1 | 00AE | Table of channelt's assigned to each of the buffers. $FF is inactive buffer. |
RECL | 00B5 | Table of lo bytes of record numbers for each buffer |
RECH | 00BB | Table of hi bytes of record numbers for each buffer |
NR | 00C1 | Table of next record numbers for buffers |
RS | 00C7 | Table of record size for each buffer |
SS | 00CD | Table of side sectors for each buffer |
F1PTR | 00D3 | File stream 1 pointer |
RECPTR | 00D4 | Pointer to start of record |
SSNUM | 00D5 | Number of side sector |
SSIND | 00D6 | Index to side sector |
RELPTR | 00D7 | Relative file pointer to track |
ENTSEC | 00D8 | Sector of directory entries |
ENTIND | 00DD | Index of directory entries |
FILDRV | 00E2 | Default flag, drive # (all on 1541) |
PATTYP | 00E7 | Pattern, replace, closed-flags, type |
FILTYP | 00EC | Channel file type |
CHNRDY | 00F2 | Channel status |
EIOFLG | 00F8 | Temporary for EOI |
JOBNUM | 00F9 | Current job number |
LRUTBL | 00FA | Least recently used table |
NODRV | 00FF | No drive flag for drives and 1 |
DSKVER | 0101 | DOS version taken from track 18 sector for drives 0 and 1 |
ZPEND | 0103 | Unused |
Stack area $0104-$01FF |
||
CMDBUF | 0200 | Command buffer ($0200-$0229) Disk commands such as: N0:GAMES #1,G1 that are sent to the disk drive from the computer over the serial bus are stored here. The command is parsed to locate special characters such as ':' ',' Once the command has been interpreted, ROM routines are executed to do it. |
CMDNUM | 022A | Command code number |
LINTAB | 023B | SA:LINDX table ($022B-$023D) This table indicates the current status of each data channel (secondary address) Each" position represents one channel, channel 0=$022B; 1=$022C; 2=$022D; etc.
|
CHNDAT | 023E | Channel data byte ($023E-$0243) The most recent byte read or written for each channel |
LSTCHR | 0244 | Channel last character pointer Points to the last character read or written in the buffer for each channel |
TYPE | 024A | Active file type |
STRSIZ | 024B | Length of the string |
TEMPSA | 024C | Temporary secondary address |
CMD | 024D | Temporary job command |
LSTSEC | 024E | Work area for finding best sector to do |
BUFUSE | 024F | Buffer allocation |
MDIRTY | 0251 | BAM dirty flag (drives 0/1) |
ENTFND | 0253 | Directory entry found flag |
DIRLST | 0254 | Directory listing flag |
CMDWAT | 0255 | Command waiting flag |
LINUSE | 0256 | LINDX use word |
LBUSED | 0257 | Last buffer used |
REC | 0258 | Record size. Used by directory routines |
TRKSS | 0259 | Side sector track. Used by dir routines |
SECSS | 025A | Side sector sector. Used by dir routines |
LSTJOB | 025B | Last job by buffer ($025B/C/D/E/F) |
DSEC | 0260 | Sector of directory entry by buffer |
DIND | 0266 | Index of directory entry by buffer |
ERWORD | 026C | Error word for recovery |
ERLED | 026D | Error LED mask for flashing |
PRGDRV | 026E | Last program drive |
PRGSEC | 026F | Last program sector |
WLINDX | 0270 | Write LINDX |
RLINDX | 0271 | Read LINDX |
NBTEMP | 0272 | # blocks temp |
CMDSIZ | 0274 | Command string size |
CHAR | 0275 | Character under the parser |
LIMIT | 0276 | PTR limit in comparison |
F1CNT | 0277 | File stream 1 count |
F2CNT | 0278 | File stream 2 count |
F2PTR | 0279 | File stream 2 pointer |
Parser tables ( $027A-$0289 ) |
||
FILTBL | 027A | Table of filename pointers |
FILTRK | 0280 | First file link (Track) |
FILSEC | 0285 | First file link (Sector) |
PATFLG | 028A | Pattern presence flag |
IMAGE | 028B | File stream image |
DRVCNT | 028C | Number of drive searches |
DRVFLG | 028D | Drive search flag |
LSTDRV | 028E | Last drive w/o error. Used as the default drive number. |
FOUND | 028F | Found flag in directory searches |
DIRSEC | 0290 | Directory sector |
DELSEC | 0291 | Sector of first available entry |
DELIND | 0292 | Index of first available entry |
LSTBUF | 0293 | =0 if last block |
INDEX | 0294 | Current index in buffer |
FILCNT | 0295 | Counter of file entries |
TYPFLG | 0296 | Match by type of flag |
MODE | 0297 | Active file mode (R,W) |
JOBRTN | 0298 | Job return flag |
EPTR | 0299 | Pointer for recovery |
TOFF | 029A | Total track offset |
UBAM | 029B | Last BAM update pointer |
TBAM | 029D | Track # of BAM image (drive 0/1) |
BAM | 02A1 | BAM images ($02A1-02B0) |
Output buffers ( $02B1-$02F8 ) |
||
NAMBUF | 02B1 | Directory buffer ($02B1-$02D4 ) |
ERRBUF | 02D5 | Error message buffer ($02D5-$02F8) |
WBAM | 02F9 | Don't write BAM flag. Set to at start and end of any disk command. |
NDBL | 02FA | # of disk blocks free (lo byte 0/1) |
NDBK | 02FC | # of disk blocks free (hi byte 0/1) |
PHASE | 02FE | Current phase of head stepper motor |
Data buffers ( $0300-$07FF) |
||
BUF0 | 0300 | Data buffer #0 ($0300-$03FF) |
BUF1 | 0400 | Data buffer #1 ($0400-$04FF) |
BUF2 | 0500 | Data buffer #2 ($0500-$05FF) |
BUF3 | 0600 | Data buffer #3 ($0600-$06FF) |
BUF4 | 0700 | Data buffer #4 ($0700-$07FF) BAM ONLY! |
Serial I/O 6522 ( $1800-$180F) |
||
PB | 1800 | Data port B - Serial data I/O
|
PA1 | 1801 | Data port A - Unused |
DDRB1 | 1802 | Data direCtion for port B |
DDRA1 | 1803 | Data direCtion for port A - Unused |
T1LC1 | 1804 | Timer 1 low counter |
T1HC1 | 1805 | Timer 1 high counter |
T1LL2 | 1806 | Timer 1 low latch |
T1HL2 | 1807 | Timer 1 high latch |
T2LC1 | 1808 | Timer 2 low counter |
T2HC1 | 1809 | Timer 2 high counter |
SR1 | 180A | Shift register |
ACR1 | 180B | Auxiliary control register |
PCR1 | 180C | Peripheral control register |
IFR1 | 180D | Interrupt flag register |
IER1 | 180E | Interrupt enable register |
Disk controller 6522 ( $1C00-$1C0F) |
||
DSKCNT | 1C00 | Data port B - Disk controller I/O
|
DATA2 | 1C01 | Data port A - GCR data I/O to diskette |
DDRB2 | 1C02 | Data direction for port B |
DDRA2 | 1C03 | Data direction for port A |
T1LC2 | 1C04 | Timer 1 low counter |
T1HC2 | 1C05 | Timer 1 high counter |
T1LL2 | 1C06 | Timer 1 low latch |
T1HL2 | 1C07 | Timer 1 high latch |
T2LC2 | 1C08 | Timer 2 low counter |
T2HC2 | 1C09 | Timer 2 high counter |
SR2 | 1C0A | Shift register |
ACR2 | 1C0B | Auxiliary control register |
PCR2 | 1C0C | Peripheral control register |
IFR2 | 1C0D | Interrupt flag register |
IER2 | 1C0E | Interrupt enable register |
C000 | 97 | Checksum of $Cxxx and $DXXX ROM | ||
C001 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | Unused | ||
Turn on drive-active LED |
||||
SETLDA | C100 | 78 | SEI | Set bit 3 of DSKCNT ($1C00) to turn on LED for the current drive (DRVNUM; $7F). |
C101 | A9 F7 | LDA #$F7 | ||
C103 | 2D 00 1C | AND $1C00 | ||
C106 | 48 | PHA | ||
C107 | A5 7F | LDA $7F | ||
C109 | F0 05 | BEQ $C110 | ||
C10B | 68 | PLA | ||
C10C | 09 00 | ORA #$00 | ||
C10E | D0 03 | BNE $C113 | ||
C110 | 68 | PLA | ||
C111 | 09 08 | ORA #$08 | ||
C113 | 8D 00 1C | STA $1C00 | ||
C116 | 58 | CLI | ||
C117 | 60 | RTS | ||
Turn on drive-active LED |
||||
LEDSON | C118 | 78 | SEI | Set bit 3 of DSKCNT ($1C00) to turn on drive active LED for drive 0. |
C119 | A9 08 | LDA #$08 | ||
C11B | 0D 00 1C | ORA $1C00 | ||
C11E | 8D 00 1C | STA $1C00 | ||
C121 | 58 | CLI | ||
C122 | 60 | RTS | ||
Turn off error LED |
||||
ERROFF | C123 | A9 00 | LDA #$00 | Store $00 in ERWORD ($026C) and in ERLED ($026D) to clear any error status and turn off drive-active/error LED. |
C125 | 8D 6C 02 | STA $026C | ||
C128 | 8D 6D 02 | STA $026D | ||
C12B | 60 | RTS | ||
Turn on error LED |
||||
ERRON | C12C | 78 | SEI | Store $80 in ERWORD ($026C) to ensure LED will continue to flash and set bit 3 of DSKCNT to turn the LED on using the LED mask from LEDMSK ($FECA). |
C12D | 8A | TXA | ||
C12E | 48 | PHA | ||
C12F | A9 50 | LDA #$50 | ||
C131 | 8D 6C 02 | STA $026C | ||
C134 | A2 00 | LDX #$00 | ||
C136 | BD CA FE | LDA $FECA,X | ||
C139 | 8D 6D 02 | STA $026D | ||
C13C | 0D 00 1C | ORA $1C00 | ||
C13F | 8D 00 1C | STA $1C00 | ||
C142 | 68 | PLA | ||
C143 | AA | TAX | ||
C144 | 58 | CLI | ||
C145 | 60 | RTS | ||
Parse string in command buffer |
||||
PARSXQ | C146 | A9 00 | LDA #$00 | Clear the "don't write BAM" flag, WBAM ($02F9) and move the drive number of the last successful job from LSTDRV ($028E) to DRVNUM ($7F). This makes the last used drive the default drive. |
C148 | 8D F9 02 | STA $02F9 | ||
C14B | AD 8E 02 | LDA $028E | ||
C14E | 85 7F | STA $7F | ||
C150 | 20 BC E6 | JSR $E6BC | JSR to OKERR ($E6BC) to clear any errors and move the OK error message into the error buffer. | |
C153 | A5 84 | LDA $84 | Check if the command's secondary address (ORGSA; $84) was $0F (command channel). | |
C155 | 10 09 | BPL $C160 | ||
C157 | 29 0F | AND #$0F | ||
C159 | C9 0F | CMP #$0F | ||
C15B | F0 03 | BEQ $C160 | ||
C15D | 4C B4 D7 | JMP $D7B4 | If it was not $0F, exit with a JMP to OPEN ($D7B4). | |
PS5 | C160 | 20 B3 C2 | JSR $C2B3 | If the secondary address was $0F, JSR to CMDSET ($C2B3) to interpret the command and set up the necessary variables and registers (on return .Y=0). |
C163 | B1 A3 | LDA ($A3),Y | Move first character of command from the command buffer ($0200) to CHAR ($0275). | |
C165 | 8D 75 02 | STA $0275 | ||
C168 | A2 0B | LDX #$0B | ||
PS10 | C16A | BD 89 FE | LDA $FE89,X | Search the command table (CMDTBL; $FE89) for this character. If not found, exit by loading .A with a #$31 (BAD COMMAND) and jumping to the command level error handler (CMDERR; $C1C8). |
C16D | CD 75 02 | CMP $0275 | ||
C170 | F0 08 | BEQ $C17A | ||
C172 | CA | DEX | ||
C173 | 10 F5 | BPL $C16A | ||
C175 | A9 31 | LDA #$31 | ||
C177 | 4C C8 C1 | JMP $C1C8 | ||
PS20 | C17A | 8E 2A 02 | STX $022A | If found, store the command's position in the table (the command number) into CMDNUM ($022A). Check if this command must be parsed by comparing the command number with $09. If parsing is required (NEW, RENAME, SCRATCH, COPY, & LOAD), |
C17D | E0 09 | CPX #$09 | ||
C17F | 90 03 | BCC $C184 | ||
C181 | 20 EE C1 | JSR $C1EE | JSR to TAGCMD ($C1EE) to set tables, pointers and patterns. | |
PS30 | C184 | AE 2A 02 | LDX $022A | Move the address of the appropriate ROM routine from the tables, CJUMPL ($FE95) and CJUMPH ($FEA1) into $6F/$70 (TEMP). Exit with an indirect JMP to the routine via the vector at TEMP ($6F). |
C187 | BD 95 FE | LDA $FE95,X | ||
C18A | 85 6F | STA $6F | ||
C18C | BD A1 FE | LDA $FEA1,X | ||
C18F | 85 70 | STA $70 | ||
C191 | 6C 6F 00 | JMP ($006F) | ||
Terminate command successfully |
||||
ENDCMD | C194 | A9 00 | LDA #$00 | Clear the "don't write BAM" flag, WBAM ($02F9). Load .A with the error status from ERWORD ($026C). If non-zero, an error has occurred so exit with a JMP to CMDERR ($C1C8) . |
C196 | 8D F9 02 | STA $02F9 | ||
C199 | AD 6C 02 | LDA $026C | ||
C19C | D0 2A | BNE $C1C8 | ||
C19E | A0 00 | LDY #$00 | ||
C1A0 | 98 | TYA | ||
C1A1 | 84 80 | STY $80 | ||
SCREND | C1A3 | 84 81 | STY $81 | If command completed with no errors, set TRACK ($80). SECTOR ($81), and the pointer into the command buffer, CB($A3) to $00. JSR to ERRMSG ($E6C7) and ERROFF ($C123) to clear any error status. |
C1A5 | 84 A3 | STY $A3 | ||
C1A7 | 20 C7 E6 | JSR $E6C7 | ||
C1AA | 20 23 C1 | JSR $C123 | ||
SCREN1 | C1AD | A5 7F | LDA $7F | Move current drive number from DRVNUM ($7F) to last used drive number, LSTDRV ($028E). Set the drive-busy flag, NODRV ($FF) to $00 to indicate that the drive is inactive. JSR to CLRCB ($C1BD) to zero the command buffer. JMP to FREICH ($D4DA) to clear the internal channel. |
C1AF | 8D 8E 02 | STA $028E | ||
C1B2 | AA | TAX | ||
C1B3 | A9 00 | LDA #$00 | ||
C1B5 | 95 FF | STA $FF,X | ||
C1B7 | 20 BD C1 | JSR $C1BD | ||
C1BA | 4C DA D4 | JMP $D4DA | ||
CLRCB | C1BD | A0 28 | LDY #$28 | Clear the command buffer ($0200-$0228) Erase any old command information by overwriting the old command with $00. |
C1BF | A9 00 | LDA #$00 | ||
C1C1 | 99 00 02 | STA $0200,Y | ||
C1C4 | 88 | DEY | ||
C1C5 | 10 FA | BPL $C1C1 | ||
C1C7 | 60 | RTS | ||
Command level error handling |
||||
CMDERR | C1C8 | A0 00 | LDY #$00 | Set TRACK ($80) and SECTOR ($81) to $00 and JMP to CMDER2 ($E645) . |
C1CA | 84 80 | STY $80 | ||
C1CC | 84 81 | STY $81 | ||
C1CE | 4C 45 E6 | JMP $E645 | ||
Simple parser |
||||
SIMPRS | C1D1 | A2 00 | LDX #$00 | Initialize .X and the file table pointer FILTBL ($027A) to $00. Load .A with a $3A (:) and JSR to PARSE ($C268) to scan the command string for a colon. |
C1D3 | 8E 7A 02 | STX $027A | ||
C1D6 | A9 3A | LDA #$3A | ||
C1D8 | 20 68 C2 | JSR $C268 | ||
C1DB | F0 05 | BEQ $C1E2 | On return Z=1 if ":" found and .Y points to its position in the command. If not found, leave FILTAB=$00 and exit. If ":" was found, set FILTAB=(":" position-1) and exit. All exits are with a JMP to SETANY ($C368) to set the drive number. | |
C1DD | 88 | DEY | ||
C1DE | 88 | DEY | ||
C1DF | 8C 7A 02 | STY $027A | ||
C1E2 | 4C 68 C3 | JMP $C368 | ||
Find colon (:) in command string |
||||
PRSCLN | C1E5 | A0 00 | LDY #$00 | Load .X and .Y with $00 and. A with $3A (:) and JMP to PARSE ($C268). |
C1E7 | A2 00 | LDX #$00 | ||
C1E9 | A9 3A | LDA #$3A | ||
C1EB | 4C 68 C2 | JMP $C268 | ||
Tag command string, set up CMD structure and file stream pointers |
||||
Command Structure (Bit mapped)The disk commands, RENAME, SCRATCH, NEW, and LOAD, are analyzed by this routine to determine the command structure. As the command is parsed bits in IMAGE ($028B) are set or cleared to indicate the presence or adsence of various parts of the command. Once the command has been analyzed, its structure image is checked against the correct structure for that command diven in STRUCT ($FEA5+)
|
||||
TAGCMD | C1EE | 20 E5 C1 | JSR $C1E5 | JSR to PRSCLN ($C1E5) to locate the position of the colon (:) that is a necessary part of all these commands, e.g. R0:NEWNAME=OLDNAME (Rename) |
C1F1 | D0 05 | BNE $C1F8 | ||
TC25 | C1F3 | A9 34 | LDA #$34 | If no colon was found, load .A with $34 to indicate a bad command and exit with a JMP to CMDERR ($C1C8). |
C1F5 | 4C C8 C1 | JMP $C1C8 | ||
TC30 | C1F8 | 88 | DEY | If a colon was found, set FILTAB to the colon position-1. |
C1F9 | 88 | DEY | ||
C1FA | 8C 7A 02 | STY $027A | ||
C1FD | 8A | TXA | Check if a comma was found before the colon (.X > on return from PARSE). | |
C1FE | D0 F3 | BNE $C1F3 | If a comma was found, the syntax is bad so exit via TC25 ($C1F3). | |
TC35 | C200 | A9 3D | LDA #$3D | Load .A with $3D (=) and JSR to PARSE ($C268). On return .X=0 indicates that no wild-card characters (? or *) were found. If any were found, set bit 6 (G1) of IMAGE ($028B) to indicate that the command applies to more than one file. |
C202 | 20 68 C2 | JSR $C268 | ||
C205 | 8A | TXA | ||
C206 | F0 02 | BEQ $C20A | ||
C208 | A9 40 | LDA #$40 | ||
TC40 | C20A | 09 21 | ORA #$21 | In all cases, set bit 5 (Dl) of IMAGE to indicate that a drive # is present and set bit (N2) to indicate that a second file name is given (fixed later). |
C20C | 8D 8B 02 | STA $028B | ||
C20F | E8 | INX | Increment .X and use it to set the lengths of filenames 1 and 2, F1CNT and F2CNT ($0277/8). Filename 2 will default to the same length as filename 1. | |
C210 | 8E 77 02 | STX $0277 | ||
C213 | 8E 78 02 | STX $0278 | ||
C216 | AD 8A 02 | LDA $028A | Check if PARSE found any wild cards by loading PATFLG ($028A). If any found, set bit 7 (PI) of IMAGE ($028B). | |
C219 | F0 0D | BEQ $C228 | ||
C21B | A9 80 | LDA #$80 | ||
C21D | 0D 8B 02 | ORA $028B | ||
C220 | 8D 8B 02 | STA $028B | ||
C223 | A9 00 | LDA #$00 | Set pattern flag, PATFLG ($028A) to $00 to prepare for parsing the rest of the command. | |
C225 | 8D 8A 02 | STA $028A | ||
TC50 | C228 | 98 | TYA | Check if there is any command left to parse by checking the value of .Y set by PARSE. If .Y=0, nothing left so branch to TC75 ($C254) to check structure. |
C229 | F0 29 | BEQ $C254 | ||
C22B | 9D 7A 02 | STA $027A,X | Store value from .Y in filetable, FILTBL ($027A),X. Set the pointer to the start of filename #2, F2PNT ($0279) from the current value of F1CNT ($0277). | |
C22E | AD 77 02 | LDA $0277 | ||
C231 | 8D 79 02 | STA $0279 | ||
C234 | A9 8D | LDA #$8D | Load .A with $8D (shifted CR) and JSR to PARSE ($C268) to parse the rest of the command. On return increment .X so it points to the end of the string and put the value into F2CNT ($0278). Decrement the value of .X to restore its former value. | |
C236 | 20 68 C2 | JSR $C268 | ||
C239 | E8 | INX | ||
C23A | 8E 78 02 | STX $0278 | ||
C23D | CA | DEX | ||
C23E | AD 8A 02 | LDA $028A | Check if any wild cards were found by PARSE in filename 2 by checking the pattern flag, PATFLG ($028A). If any were found, set 3 (P2) of IMAGE ($028B). | |
C241 | F0 02 | BEQ $C245 | ||
C243 | A9 08 | LDA #$08 | ||
TC60 | C245 | EC 77 02 | CPX $0277 | Check if there was a second filename by checking if .X = F1CNT. If second file name is only 1 chr long, branch to TC70. |
C248 | F0 02 | BEQ $C24C | ||
C24A | 09 04 | ORA #$04 | Set bit 2 to indicate that the command implies more than one second file name. | |
TC70 | C24C | 09 03 | ORA #$03 | Set bit 1 to indicate that a second drive is specified and bit to indicate that a second file name is given. EOR this with IMAGE (clears bit 0) and store the result back into IMAGE ($028B) . |
C24E | 4D 8B 02 | EOR $028B | ||
C251 | 8D 8B 02 | STA $028B | ||
TC75 | C254 | AD 8B 02 | LDA $028B | Check IMAGE against the entry for that command (CMD number from CMDNUM, $022A) in the structure table, STRUCT ($FEA5+) If match, syntax is OK; exit with an RTS |
C257 | AE 2A 02 | LDX $022A | ||
C25A | 3D A5 FE | AND $FEA5,X | ||
C25D | D0 01 | BNE $C260 | ||
C25F | 60 | RTS | ||
TC80 | C260 | 8D 6C 02 | STA $026C | Store IMAGE in ERWORD ($026C). Load .A with a $30 to indicate a bad syntax and exit with a JMP to CMDERR ($C1C8) . |
C263 | A9 30 | LDA #$30 | ||
C265 | 4C C8 C1 | JMP $C1C8 | ||
Parse stringOn entry, .A contains the character to be found in the string, .Y points to the the character in the string where the scan is to start, and .X points into the file table, FILTAB,X. The routine scans the string for special characters "*". "?", and "," as well as the desired character. In scanning the string .Y is used as a pointer to the character in the command string being examined and .X is a pointer into the file table, FILTAB (S027B+) for storing the positions (.Y value) of the start & end of file names that are found. When a wild card (* or ?) is found, the pattern flag PATFLG ($028A) is incremented. When a comma is found, its position is noted in the file table, FILTAB and a check is made to ensure that not too many file names are present. When the special character is found or the end of the command is reached, the routine ends. If no wild cards have been found, the pattern type, PATTYP,X is set to $80. Otherwise it is left unchanged. On exit, .Y=0 and the Z flag =0 if the desired character has not been found. If it has been found, .Y = the position of the character and the Z flag is set. |
||||
PARSE | C268 | 8D 75 02 | STA $0275 | Store the desired character in CHAR ($0275) . |
PR10 | C26B | CC 74 02 | CPY $0274 | Start of loop using .Y as a counter to scan the command string. If .Y is greater than or equal to the length of the command string, CMDSIZE ($0274) , branch to PR30 ($C29E) . |
C26E | B0 2E | BCS $C29E | ||
C270 | B1 A3 | LDA ($A3),Y | Load command string character into .A and increment .Y counter. Check if it is the desired character. If it is, branch to PR35 ($C2A0) . | |
C272 | C8 | INY | ||
C273 | CD 75 02 | CMP $0275 | ||
C276 | F0 28 | BEQ $C2A0 | ||
C278 | C9 2A | CMP #$2A | Check if it is a wild card ("*" or "?"). If not, branch to PR25 ($C283). | |
C27A | F0 04 | BEQ $C280 | ||
C27C | C9 3F | CMP #$3F | ||
C27E | D0 03 | BNE $C283 | ||
PR20 | C280 | EE 8A 02 | INC $028A | Increment the pattern flag, PATFLG ($028A) to count the # of wild cards. |
PR25 | C283 | C9 2C | CMP #$2C | Check if it is a comma (","). If not, branch back to PR10 to get next command string character. |
C285 | D0 E4 | BNE $C26B | ||
C287 | 98 | TYA | Transfer character count from .Y to .A and store in the file table, FILTAB+1,X ($027B,X) to indicate where the file name ends. Load .A with the pattern flag PATFLG and AND it with $7F. If the result is zero (no wild cards found) , branch to PR28. | |
C288 | 9D 7B 02 | STA $027B,X | ||
C28B | AD 8A 02 | LDA $028A | ||
C28E | 29 7F | AND #$7F | ||
C290 | F0 07 | BEQ $C299 | ||
C292 | A9 80 | LDA #$80 | Wild cards were present, so store $80 in PATTYP,X ($E7,X) to indicate this. Also store $80 into PATFLG to zero the count of wild cards but indicate that there are wild cards in the string. | |
C294 | 95 E7 | STA $E7,X | ||
C296 | 8D 8A 02 | STA $028A | ||
PR28 | C299 | E8 | INX | Increment .X (counts number of files & points into FILTAB) and compare it to $04 (the maximum number of file names allowed in a command string). If the maximum has not been exceeded, branch back to PR10 to continue the scan. |
C29A | E0 04 | CPX #$04 | ||
C29C | 90 CD | BCC $C26B | ||
PR30 | C29E | A0 00 | LDY #$00 | Load .Y with $00 to indicate that the desired character was not found. |
PR35 | C2A0 | AD 74 02 | LDA $0274 | Store a copy of the command size, CMDSIZ ($0274) into the file table, FILTAB+1,X ($027B,X). Load the pattern flag, PATFLG and AND it with $7F. If the result is 0, no wild cards have been found so branch to PR4 0. |
C2A3 | 9D 7B 02 | STA $027B,X | ||
C2A6 | AD 8A 02 | LDA $028A | ||
C2A9 | 29 7F | AND #$7F | ||
C2AB | F0 04 | BEQ $C2B1 | ||
C2AD | A9 80 | LDA #$80 | Wild cards were present, so store $80 in PATTYP,X ($E7,X) to indicate this. | |
C2AF | 95 E7 | STA $E7,X | ||
PR40 | C2B1 | 98 | TYA | Transfer character count from .Y to .A. This sets the Z flag if the desired character has not been found. |
C2B2 | 60 | RTS | ||
Initialize command tables & pointersFind length of command string and zero all variables and pointers. |
||||
CMDSET | C2B3 | A4 A3 | LDY $A3 | Load .Y from BUFTAB+CBPTR ($A3). This is the length of the command that was sent from the computer. If .Y=0, branch to CS08 ($C2CB) . |
C2B5 | F0 14 | BEQ $C2CB | ||
C2B7 | 88 | DEY | Decrement .Y and if .Y=0, branch to CS07 ($C2CA) . | |
C2B8 | F0 10 | BEQ $C2CA | ||
C2BA | B9 00 02 | LDA $0200,Y | Load .A with the character from the command buffer, CMDBUF,Y ($0200, Y) and see if it is a carriage return ($0D). If it is, branch to CS08 ($C2CB) . | |
C2BD | C9 0D | CMP #$0D | ||
C2BF | F0 0A | BEQ $C2CB | ||
C2C1 | 88 | DEY | Decrement .Y and load the next character from the command buffer. If this is a carriage return ($0D). branch to CS08 ($C2CB). If not, increment .Y | |
C2C2 | B9 00 02 | LDA $0200,Y | ||
C2C5 | C9 0D | CMP #$0D | ||
C2C7 | F0 02 | BEQ $C2CB | ||
C2C9 | C8 | INY | ||
CS07 | C2CA | C8 | INY | Increment .Y pointer into command buffer |
CS08 | C2CB | 8C 74 02 | STY $0274 | Store length of command (.Y) in CMDSIZ ($027B). Compare length (.Y) with the maximum allowable length ($2A) to set the carry flag. Load .Y with $FF. If command length was OK, branch to CMDRST. |
C2CE | C0 2A | CPY #$2A | ||
C2D0 | A0 FF | LDY #$FF | ||
C2D2 | 90 08 | BCC $C2DC | ||
C2D4 | 8C 2A 02 | STY $022A | Command over-size so set command number ($022A) to $FF, load .A with $32 to indicate a TOO LONG ERROR and exit with a JMP to CMDERR ($C1C8). | |
C2D7 | A9 32 | LDA #$32 | ||
C2D9 | 4C C8 C1 | JMP $C1C8 | ||
CMDRST | C2DC | A0 00 | LDY #$00 | Zero all important variables & pointers:
|
C2DE | 98 | TYA | ||
C2DF | 85 A3 | STA $A3 | ||
C2E1 | 8D 58 02 | STA $0258 | ||
C2E4 | 8D 4A 02 | STA $024A | ||
C2E7 | 8D 96 02 | STA $0296 | ||
C2EA | 85 D3 | STA $D3 | ||
C2EC | 8D 79 02 | STA $0279 | ||
C2EF | 8D 77 02 | STA $0277 | ||
C2F2 | 8D 78 02 | STA $0278 | ||
C2F5 | 8D 8A 02 | STA $028A | ||
C2F8 | 8D 6C 02 | STA $026C | ||
C2FB | A2 05 | LDX #$05 | ||
C2FD | 9D 79 02 | STA $0279,X | ||
C300 | 95 D7 | STA $D7,X | ||
C302 | 95 DC | STA $DC,X | ||
C304 | 95 E1 | STA $E1,X | ||
C306 | 95 E6 | STA $E6,X | ||
C308 | 9D 7F 02 | STA $027F,X | ||
C30B | 9D 84 02 | STA $0284,X | ||
C30E | CA | DEX | ||
C30F | D0 EC | BNE $C2FD | ||
C311 | 60 | RTS | ||
Set first drive & table pointers |
||||
ONEDRV | C312 | AD 78 02 | LDA $0278 | Change pointer to end of the first file name (F1CNT; $0277) to point to the end of the second file name (use value from F2CNT; $0278). Store $01 in F2CNT and in F2PTR ($0279) to clear these variables |
C315 | 8D 77 02 | STA $0277 | ||
C318 | A9 01 | LDA #$01 | ||
C31A | 8D 78 02 | STA $0278 | ||
C31D | 8D 79 02 | STA $0279 | ||
ALLDRS | C320 | AC 8E 02 | LDY $028E | Set up all drives from F2CNT: Load .Y with last drive used from LSTDRV ($028E) and .X with $00. |
C323 | A2 00 | LDX #$00 | ||
AD10 | C325 | 86 D3 | STX $D3 | Save .X into F1PTR ($D3). Load .A from FILTAB,X ($027A,X) so it points to the start of the Xth file specified in the command string. |
C327 | BD 7A 02 | LDA $027A,X | ||
C32A | 20 3C C3 | JSR $C33C | JSR to SETDRV ($C33C) to set drive #. On return .Y contains the drive number specified in the command or the default. NOTE: Bits represent drives (If bit 7 set, use default. Bit = drive #0/1) | |
C32D | A6 D3 | LDX $D3 | Recover .X pointer from F1PTR. Store .A in FILTAB,X ($027A,X). Move drive # from .Y to .A and store in FILDRV, X ($027A,X) | |
C32F | 9D 7A 02 | STA $027A,X | ||
C332 | 98 | TYA | ||
C333 | 95 E2 | STA $E2,X | ||
C335 | E8 | INX | Increment .X pointer and compare it to F2CNT ($0278) to see if any more files were specified. If more, branch back to AD10 to do the next one. If not, RTS | |
C336 | EC 78 02 | CPX $0278 | ||
C339 | 90 EA | BCC $C325 | ||
C33B | 60 | RTS | ||
Set drive # from text or default to 0On entry and exit .A is an index into the command buffer. On entry .Y is the default drive #. On exit it is the drive specified or the default drive. |
||||
SETDRV | C33C | AA | TAX | Move pointer into command buffer from .A to .X |
C33D | A0 00 | LDY #$00 | Load .Y with $00 to ensure that the 1541' s default drive is ALWAYS DRIVE #0 | |
C33F | A9 3A | LDA #$3A | Load .A with $3A (:) to prepare to hunt for a colon (drive # is just before :). | |
C341 | DD 01 02 | CMP $0201,X | Check for colon in command string at CMDBUF+1,X ($0201, X). Picks up syntax: X#: FILENAME as in SO: JUNK If found, branch to SD40. | |
C344 | F0 0C | BEQ $C352 | ||
C346 | DD 00 02 | CMP $0200,X | Check for colon in command string at CMDBUF,X ($0200, X). Picks up default drive syntax as in S:JUNK If colon NOT found, branch to SD40. | |
C349 | D0 16 | BNE $C361 | ||
C34B | E8 | INX | Colon found so increment pointer (.X) so it points to the first character in the filename. | |
SD20 | C34C | 98 | TYA | Transfer .Y to .A to set up the default drive |
SD22 | C34D | 29 01 | AND #$01 | AND .A with $01 to ensure drive number in ASCII form ($30 or $31) is converted to $00 or $01. |
SD24 | C34F | A8 | TAY | Transfer .A to .Y to restore drive #. Transfer .X to .A to restore index into command string and exit with an RTS. |
C350 | 8A | TXA | ||
C351 | 60 | RTS | ||
Set drive # from command string with the syntax: X#: FILENAMEOn entry .X points to the # in the command string. |
||||
SD40 | C352 | BD 00 02 | LDA $0200,X | Load .A with the drive number (in ASCII) from CMDBUF,X ($0200, X). |
C355 | E8 | INX | Increment .X twice so it points to the first character in the file name. | |
C356 | E8 | INX | ||
C357 | C9 30 | CMP #$30 | Compare .A (drive number) to $30 (dr#0) . If equal, branch back to SD22 ($C34D) | |
C359 | F0 F2 | BEQ $C34D | ||
C35B | C9 31 | CMP #$31 | Compare .A (drive number) to $31 (dr#l) . If equal, branch back to SD22 ($C34D) If not equal, must be default drive so branch back to SD20 ($C34C) . | |
C35D | F0 EE | BEQ $C34D | ||
C35F | D0 EB | BNE $C34C | ||
SD50 | C361 | 98 | TYA | Set drive # from command string with the syntax: X#,FILE or xx=FILE. Transfer the drive number from .Y to .A. |
C362 | 09 80 | ORA #$80 | OR .A with $80 to set the default drive bit and then AND the result with $81 to mask off any odd bits. Branch back to SD24 ($C34F) to terminate routine. | |
C364 | 29 81 | AND #$81 | ||
C366 | D0 E7 | BNE $C34F | ||
Set drive # from any configuration |
||||
SETANY | C368 | A9 00 | LDA #$00 | Set IMAGE ($028B) to $00. |
C36A | 8D 8B 02 | STA $028B | ||
C36D | AC 7A 02 | LDY $027A | Load .Y from FILTBL ($027A) . | |
SA05 | C370 | B1 A3 | LDA ($A3),Y | Load .A with the (CB) ,Y character from the command string and JSR to TST0V1 to test for a "0" or "1" . |
C372 | 20 BD C3 | JSR $C3BD | ||
C375 | 10 11 | BPL $C388 | On return .A contains $00 or $01 if the drive was specified. If not specified, .A is $80 or $81. If the drive number was given, branch to SA20 ($C388) . | |
C377 | C8 | INY | Increment the pointer into the command string (.Y). Compare the pointer value to the command length (CMDSIZ; $0274) to see if we are at the end. If we are, branch to SA10 ($C383) . | |
C378 | CC 74 02 | CPY $0274 | ||
C37B | B0 06 | BCS $C383 | ||
C37D | AC 74 02 | LDY $0274 | If not "0" or "1", set the pointer (.Y) to the end of the command less one (so it points to the last character before the RETURN to pick up things like V0) and loop back to SA05 ($C370). | |
C380 | 88 | DEY | ||
C381 | D0 ED | BNE $C370 | ||
SA10 | C383 | CE 8B 02 | DEC $028B | Decrement IMAGE (becomes $FF) to flag a default drive status and load .A with a $00 to ensure default to on the 1541. |
C386 | A9 00 | LDA #$00 | ||
SA20 | C388 | 29 01 | AND #$01 | AND the drive number in .A with $01, and store the result in the current drive number, DRVNUM ($7F) . |
C38A | 85 7F | STA $7F | ||
C38C | 4C 00 C1 | JMP $C100 | Exit with a JMP to SETLDS ($C100) to turn on the drive active light. | |
Toggle drive number |
||||
TOGDRV | C38F | A5 7F | LDA $7F | Load .A with current drive number from DRVNUM ($7F). EOR it with $01 to flip bit #0, AND it with $01 to mask off the bits 1-7, and store the result back in DRVNUM ($7F) . |
C391 | 49 01 | EOR #$01 | ||
C393 | 29 01 | AND #$01 | ||
C395 | 85 7F | STA $7F | ||
C397 | 60 | RTS | ||
Set pointers to one file stream and check type |
||||
FS1SET | C398 | A0 00 | LDY #$00 | Zero .Y and load .A with the pointer to the end of file name 1 (F1CNT; $0277) . |
C39A | AD 77 02 | LDA $0277 | ||
C39D | CD 78 02 | CMP $0278 | Compare .A to the pointer to the end of file name 2 (F2CNT; $0278). If equal, there is no second file so branch to FS15 ($C3B8). | |
C3A0 | F0 16 | BEQ $C3B8 | ||
C3A2 | CE 78 02 | DEC $0278 | Decrement F2CNT and load .Y with its value. Load .A with the pointer to the filetype in the command string from FILTAB,Y ($027A,Y). Transfer this value to .Y and use it to load the file type into .A from the command string (CB) ,Y. | |
C3A5 | AC 78 02 | LDY $0278 | ||
C3A8 | B9 7A 02 | LDA $027A,Y | ||
C3AB | A8 | TAY | ||
C3AC | B1 A3 | LDA ($A3),Y | Load .Y with $04 (the number of file types less 1) . | |
C3AE | A0 04 | LDY #$04 | ||
FS10 | C3B0 | D9 BB FE | CMP $FEBB,Y | Loop to compare the file type in .A to the list of possible file types ,TYPLST,Y When a match occurs, branch to FS15 ($C3B8). If no match found this time, decrement .Y and, if there are any file types left, loop back to FS10. NOTE: if no match occurs, file assumed to be DEL. |
C3B3 | F0 03 | BEQ $C3B8 | ||
C3B5 | 88 | DEY | ||
C3B6 | D0 F8 | BNE $C3B0 | ||
FS15 | C3B8 | 98 | TYA | Transfer file type from .Y to .A and store in TYPFLG ($0296). |
C3B9 | 8D 96 02 | STA $0296 | ||
C3BC | 60 | RTS | ||
Test if character in .A is ASCII or 1 |
||||
TST0V1 | C3BD | C9 30 | CMP #$30 | Compare .A to ASCII "0" ($30) and then to ASCII "1" ($31). If a match in either case, branch to T0V1. OR .A with $80 to set bit 7 to indicate no match was found. |
C3BF | F0 06 | BEQ $C3C7 | ||
C3C1 | C9 31 | CMP #$31 | ||
C3C3 | F0 02 | BEQ $C3C7 | ||
C3C5 | 09 80 | ORA #$80 | ||
T0V1 | C3C7 | 29 81 | AND #$81 | AND .A with $81 to convert ASCII to HEX and preserve bit 7. |
C3C9 | 60 | RTS | ||
Determine optimal search for LOOKUP and FINFIL |
||||
OPTSCH | C3CA | A9 00 | LDA #$00 | Zero TEMP ($6F) and DRVFLG ($028D) and push $00 onto the stack. Load .X with value from F2CNT ($0278). Note: TEMP is the drive mask. |
C3CC | 85 6F | STA $6F | ||
C3CE | 8D 8D 02 | STA $028D | ||
C3D1 | 48 | PHA | ||
C3D2 | AE 78 02 | LDX $0278 | ||
OS10 | C3D5 | 68 | PLA | Pull .A from the stack and OR it with the value in TEMP ($6F). Push the result back onto the stack. Load .A with $01 and store this value in TEMP. Decrement .X (pointer into file table). If no files left (.X=$FF), branch to $OS30. |
C3D6 | 05 6F | ORA $6F | ||
C3D8 | 48 | PHA | ||
C3D9 | A9 01 | LDA #$01 | ||
C3DB | 85 6F | STA $6F | ||
C3DD | CA | DEX | ||
C3DE | 30 0F | BMI $C3EF | ||
C3E0 | B5 E2 | LDA $E2,X | Load .A with the drive for the file from FILDRV,X ($E2,X). If this file uses the default drive (bit 7 set), branch to OS15. Do two ASL's on TEMP ($6F). | |
C3E2 | 10 04 | BPL $C3E8 | ||
C3E4 | 06 6F | ASL $6F | ||
C3E6 | 06 6F | ASL $6F | ||
OS15 | C3E8 | 4A | LSR | Do one LSR on .A. If drive number in .A was 1, the carry bit is set so branch back to OS10. |
C3E9 | 90 EA | BCC $C3D5 | ||
C3EB | 06 6F | ASL $6F | Since drive number was 0, do one ASL on TEMP ($6F) and branch back to OS10. | |
C3ED | D0 E6 | BNE $C3D5 | ||
OS30 | C3EF | 68 | PLA | Pull .A from the stack and transfer this value to .X. Use this value as an index and load .A with a value from the search table, SCHTBL-1,X ($C43F,X). Push this value onto the stack, AND it with $03, and store the result in DRVCNT ($028C). Pull the original value off the stack and do an ASL. If bit 7 is not set, branch to OS40. |
C3F0 | AA | TAX | ||
C3F1 | BD 3F C4 | LDA $C43F,X | ||
C3F4 | 48 | PHA | ||
C3F5 | 29 03 | AND #$03 | ||
C3F7 | 8D 8C 02 | STA $028C | ||
C3FA | 68 | PLA | ||
C3FB | 0A | ASL | ||
C3FC | 10 3E | BPL $C43C | ||
C3FE | A5 E2 | LDA $E2 | If bit 7 was set, load A. with the value from FILDRV ($E2) . | |
OS35 | C400 | 29 01 | AND #$01 | AND .A with $01 and store the result in DRVNUM ($7F). Load .A with DRVCNT ( $028C) and if $00, only one drive is addressed so branch to OS60. |
C402 | 85 7F | STA $7F | ||
C404 | AD 8C 02 | LDA $028C | ||
C407 | F0 2B | BEQ $C434 | ||
C409 | 20 3D C6 | JSR $C63D | JSR to AUTOI ($C63D) to check the drive status and initialize it if necessary. On return, branch to OS70 if the drive is ready (. A=0) . | |
C40C | F0 12 | BEQ $C420 | ||
C40E | 20 8F C3 | JSR $C38F | ||
C411 | A9 00 | LDA #$00 | ||
C413 | 8D 8C 02 | STA $028C | ||
C416 | 20 3D C6 | JSR $C63D | ||
C419 | F0 1E | BEQ $C439 | ||
OS45 | C41B | A9 74 | LDA #$74 | Drive is not ready so load .A with $74 to indicate the drive is not ready and JSR to CMDERR ($C1C8). |
C41D | 20 C8 C1 | JSR $C1C8 | ||
OS50 | C420 | 20 8F C3 | JSR $C38F | JSR to TOGDRV ($C38F) to switch drives and JSR to AUTOI ($C63D) to check this drive's status and init it if necessary. On return, save the processor status on the stack. JSR to TOGDRV to switch back to the first drive. On return, pull the status back off the stack. If the second drive is active, branch to OS70. |
C423 | 20 3D C6 | JSR $C63D | ||
C426 | 08 | PHP | ||
C427 | 20 8F C3 | JSR $C38F | ||
C42A | 28 | PLP | ||
C42B | F0 0C | BEQ $C439 | ||
C42D | A9 00 | LDA #$00 | Since second drive is not active, set DRVCNT ($020C) to $00 to indicate only one drive addressed and branch to OS70. | |
C42F | 8D 8C 02 | STA $028C | ||
C432 | F0 05 | BEQ $C439 | ||
OS60 | C434 | 20 3D C6 | JSR $C63D | JSR to AUTOI ($C63D) to check the drive status and initialize it if necessary. On return, branch to OS45 if the drive is NOT ready (.AO0) . |
C437 | D0 E2 | BNE $C41B | ||
OS70 | C439 | 4C 00 C1 | JMP $C100 | Teminate routine with a JMP to SETLDS ($C100) to turn on the drive active LEDs |
OS45 | C43C | 2A | ROL | Do a ROL on the value in .A and JMP to OS35 ($C400). |
C43D | 4C 00 C4 | JMP $C400 | ||
SCHTBL | C440 | 00 80 41 01 01 01 01 81 81 81 81 42 42 42 42 | Search Table
| |
Look up all files in command string in the directory and fill tables with info |
||||
LOOKUP | C44F | 20 CA C3 | JSR $C3CA | JSR to OPTSCH to find optimal search pattern and turn on drive active LEDs. |
LK05 | C452 | A9 00 | LDA #$00 | Store $00 in DELIND ($0292). to indicate that we are NOT looking for a deleted or unused directory entry. But, for one or more specific file names. JSR to SRCHST ($C5AC) to start the search process. |
C454 | 8D 92 02 | STA $0292 | ||
C457 | 20 AC C5 | JSR $C5AC | ||
C45A | D0 19 | BNE $C475 | On return, branch to LK25 if a valid file name was found (Z flag =0) | |
LK10 | C45C | CE 8C 02 | DEC $028C | Since no file name was found, decrement DRVCNT ($028C). the number of drive searches to be made. If any more left (DRVCNT >= 0), branch to LK15. |
C45F | 10 01 | BPL $C462 | ||
C461 | 60 | RTS | Since there are no more drive searches to be done, exit with an RTS. | |
LK15 | C462 | A9 01 | LDA #$01 | Store $01 in DRVFLG ($028D) and JSR to TOGDRV ($C38F) to switch drives. JSR to SETLDS ($C100) to turn on the other LED. Then JMP back to LK05 to begin the search on the other drive. |
C464 | 8D 8D 02 | STA $028D | ||
C467 | 20 8F C3 | JSR $C38F | ||
C46A | 20 00 C1 | JSR $C100 | ||
C46D | 4C 52 C4 | JMP $C452 | ||
LK20 | C470 | 20 17 C6 | JSR $C617 | JSR to SEARCH ($C617) to read the next valid file name in the directory. |
C473 | F0 10 | BEQ $C485 | On return, branch to LK30 to abandon the search if a valid file name was NOT found (Z flag = 1) . | |
LK25 | C475 | 20 D8 C4 | JSR $C4D8 | JSR to COMPAR ($C4D8) to compare the list, of files found with list of those required. On return, FOUND ($028F) is if all files have NOT been found. |
C478 | AD 8F 02 | LDA $028F | Load .A with the value from FOUND. If not all the files have been found yet, branch to LK26 to continue the search. | |
C47B | F0 01 | BEQ $C47E | ||
C47D | 60 | RTS | All files have been found so exit from the routine with an RTS. | |
LK26 | C47E | AD 53 02 | LDA $0253 | Load .A with the value from ENTFND ($0253) to check if the most recent compare found a match. If not (.A=$FF), branch to LK20 to search directory for another valid file name. If a match was found, branch back to LK25 to try again. |
C481 | 30 ED | BMI $C470 | ||
C483 | 10 F0 | BPL $C475 | ||
LK30 | C485 | AD 8F 02 | LDA $028F | Load .A with the value from FOUND. If not all the files have been found yet, branch to LK10 to continue the search. |
C488 | F0 D2 | BEQ $C45C | ||
C48A | 60 | RTS | All files found so exit with an RTS. | |
Find next file name matching any file in stream & return with entry stuffed into tables |
||||
FFRE | C48B | 20 04 C6 | JSR $C604 | JSR to SRRE ($C604) to set up and read in the next block of directory entries. |
C48E | F0 1A | BEQ $C4AA | If no files found, branch to FF10. | |
C490 | D0 28 | BNE $C4BA | If files were found, branch to FF25. | |
FF15 | C492 | A9 01 | LDA #$01 | Store $01 in DRVFLG ($028D) and JSR to TOGDRV ($C38F) to switch to the other drive. JSR to SETLDS ($C100) to turn on the new drive active light. |
C494 | 8D 8D 02 | STA $028D | ||
C497 | 20 8F C3 | JSR $C38F | ||
C49A | 20 00 C1 | JSR $C100 | ||
Find starting entry in the directory |
||||
FFST | C49D | A9 00 | LDA #$00 | Store $00 in DELIND ($0292),to indicate that we are NOT looking for a deleted or unused directory entry. But, for one or more specific file names. JSR to SRCHST ($C5AC) to start the search process. |
C49F | 8D 92 02 | STA $0292 | ||
C4A2 | 20 AC C5 | JSR $C5AC | ||
C4A5 | D0 13 | BNE $C4BA | On return, branch to FF25 if a valid file name was found (Z flag = 0) | |
C4A7 | 8D 8F 02 | STA $028F | Store .A value in FOUND ($028F) . | |
FF10 | C4AA | AD 8F 02 | LDA $028F | Load .A from FOUND ($028F) .If non-zero, all files found so branch to FF40 & exit |
C4AD | D0 28 | BNE $C4D7 | ||
C4AF | CE 8C 02 | DEC $028C | Since there is nothing more on this drive, decrement DRVCNT by 1. If any more drives left, branch to FF15 to try the other drive. If none left, do an RTS | |
C4B2 | 10 DE | BPL $C492 | ||
C4B4 | 60 | RTS | ||
Continue scan of directory |
||||
FNDFIL | C4B5 | 20 17 C6 | JSR $C617 | JSR to SEARCH ($C617) to retrieve the next valid file name from the directory. |
C4B8 | F0 F0 | BEQ $C4AA | On return, branch to FF10 if no more entries available on this drive. | |
FF25 | C4BA | 20 D8 C4 | JSR $C4D8 | JSR to COMPAR ($C4D8) to see if any of the names found match the ones needed. |
C4BD | AE 53 02 | LDX $0253 | On return, load .X from ENTFND ($0253). If a match on a name was found (.X<128), branch to FF30 to check the file type. If no match found (.X>127), load .A with the value from FOUND ($028F) to check if all files have been found. If not(.A=0), branch back to FNDFIL to load another name from the directory. | |
C4C0 | 10 07 | BPL $C4C9 | ||
C4C2 | AD 8F 02 | LDA $028F | ||
C4C5 | F0 EE | BEQ $C4B5 | ||
C4C7 | D0 0E | BNE $C4D7 | If .AO0, all files have been found so branch to FF40 and exit with an RTS. | |
FF30 | C4C9 | AD 96 02 | LDA $0296 | Check the file type flag, TYPFLG ($0296) . If it is $00, there is no file type restriction so branch to FF40 and exit. |
C4CC | F0 09 | BEQ $C4D7 | ||
C4CE | B5 E7 | LDA $E7,X | Load the file pattern type from PATTYP,X ($E7,X), AND it with the file type mask#$07, and compare it to the value in TYPFLG ($0296). If the file types do not match, branch back to FNDFIL to continue the search. | |
C4D0 | 29 07 | AND #$07 | ||
C4D2 | CD 96 02 | CMP $0296 | ||
C4D5 | D0 DE | BNE $C4B5 | ||
FF40 | C4D7 | 60 | RTS | Terminate the routine with an RTS. |
Compare all file names in command list with each valid entry in directory.Any matches are tabulated. |
||||
COMPAR | C4D8 | A2 FF | LDX #$FF | Set the found-entry flag, ENTFND ($0253) to $FF and zero the pattern flag PATFLG (S028A). JSR to CMPCHK ($C589) to check the file table for unfound files. If there are unfound files (Z flag = 1), branch to CP10 to begin comparing. |
C4DA | 8E 53 02 | STX $0253 | ||
C4DD | E8 | INX | ||
C4DE | 8E 8A 02 | STX $028A | ||
C4E1 | 20 89 C5 | JSR $C589 | ||
C4E4 | F0 06 | BEQ $C4EC | ||
CP02 | C4E6 | 60 | RTS | Terminate routine with an RTS. |
CP05 | C4E7 | 20 94 C5 | JSR $C594 | JSR to CC10 ($C594) to set F2PTR ($0279) to point to the next file needed on this drive. On return, branch to CP02 to exit if no more files needed on this drive. |
C4EA | D0 FA | BNE $C4E6 | ||
CP10 | C4EC | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F) and EOR it with the drive number specified for the file, FILDRV,X ($E2,X). LSR the result. If the carry flag is clear, the drive number is correct for this file so branch to CP20 to find the name in the directory list. |
C4EE | 55 E2 | EOR $E2,X | ||
C4F0 | 4A | LSR | ||
C4F1 | 90 0B | BCC $C4FE | ||
C4F3 | 29 40 | AND #$40 | AND the value in .A with $40 to check if we are to use the default drive (NOTE: $40 rather than $80 because of the LSR) . If we can not use the default drive, branch back to CP05 to set up the next file name on our list of files needed. | |
C4F5 | F0 F0 | BEQ $C4E7 | ||
C4F7 | A9 02 | LDA #$02 | Compare DRVCNT ($028C) with $02. If equal. don't use default drive so branch back to CP05. | |
C4F9 | CD 8C 02 | CMP $028C | ||
C4FC | F0 E9 | BEQ $C4E7 | ||
At this point we have a match on the drive numbers so check the directory entries to see if we can match a name. |
||||
CP20 | C4FE | BD 7A 02 | LDA $027A,X | Load .A with the pointer to the position of the required file name from FILTBL,X ($027A,X) and transfer this value to .X. |
C501 | AA | TAX | ||
C502 | 20 A6 C6 | JSR $C6A6 | JSR to FNDLMT to find the end of the command string. On return, load the pointer into the directory buffer (.Y) with $03 (so it points past the file type, track and sector) and JMP to CP33. | |
C505 | A0 03 | LDY #$03 | ||
C507 | 4C 1D C5 | JMP $C51D | ||
CP30 | C50A | BD 00 02 | LDA $0200,X | Compare the .Xth character in the command string (the required filename) with the .Yth character in the directory buffer (the directory entry). If equal , branch to CP32 to set up for the next character. |
C50D | D1 94 | CMP ($94),Y | ||
C50F | F0 0A | BEQ $C51B | ||
C511 | C9 3F | CMP #$3F | No exact match so check if the command buffer character is a "?" which will match any character. If not, branch to to CP05 to try the next file name. | |
C513 | D0 D2 | BNE $C4E7 | ||
C515 | B1 94 | LDA ($94),Y | Compare the character we just used from the directory buffer with $A0 to see if we've reached the end of the name. If we have, branch to CP0 5 to try the next file name. | |
C517 | C9 A0 | CMP #$A0 | ||
C519 | F0 CC | BEQ $C4E7 | ||
CP32 | C51B | E8 | INX | Increment .X and .Y |
C51C | C8 | INY | ||
CP33 | C51D | EC 76 02 | CPX $0276 | Compare .X with the length of the command string, LIMIT ($0276). If we are at the at the end, branch to CP34. |
C520 | B0 09 | BCS $C52B | ||
C522 | BD 00 02 | LDA $0200,X | Check if the new character in the file name, CMDBUF,X ($0200, X) is a "*". If it is, it matches everything so branch to CP40 to tabulate this match. | |
C525 | C9 2A | CMP #$2A | ||
C527 | F0 0C | BEQ $C535 | ||
C529 | D0 DF | BNE $C50A | If not a "*", branch to CP30 to keep on matching. | |
CP34 | C52B | C0 13 | CPY #$13 | Compare .Y to $13 to see if we are at the end of the name in the directory. If we are, branch to CP40 to tabulate. |
C52D | B0 06 | BCS $C535 | ||
C52F | B1 94 | LDA ($94),Y | If not at the limit, check the character in the directory entry name. If it isn't an $A0, we did not get to the end of the name so branch back to CP05 to try again | |
C531 | C9 A0 | CMP #$A0 | ||
C533 | D0 B2 | BNE $C4E7 | ||
CP40 | C535 | AE 79 02 | LDX $0279 | The filenames match so keep track of it by storing the pointer to the entry from F2PNT ($0279) intoENTFND ($0253). |
C538 | 8E 53 02 | STX $0253 | ||
C53B | B5 E7 | LDA $E7,X | Get the file type pattern ($80. $81 , etc) from PATTYP,X ($E7,X), AND it with $80, and store it in PSTFLG. | |
C53D | 29 80 | AND #$80 | ||
C53F | 8D 8A 02 | STA $028A | ||
C542 | AD 94 02 | LDA $0294 | Get the pointer to the directory entry from INDEX ($0294) and store it in the entry index, ENTIND,X ($DD,X) . | |
C545 | 95 DD | STA $DD,X | ||
C547 | A5 81 | LDA $81 | Get the sector on track 18 on which the entry is stored from SECTOR ($81) and store it in, ENTSEC,X ($D8,X). | |
C549 | 95 D8 | STA $D8,X | ||
C54B | A0 00 | LDY #$00 | Zero .Y and load .A with the file type of this directory entry from (DIRBUF) ,Y ($94) ,Y. Increment .Y. Save the type on the stack. AND the type with $40 to see if this is a locked file type, and store the result in TEMP ($6F). Pull the file type off the stack and AND it with $DF ($FF-$20). If the result is > 127 (the replacement bit not set). branch to CP42 | |
C54D | B1 94 | LDA ($94),Y | ||
C54F | C8 | INY | ||
C550 | 48 | PHA | ||
C551 | 29 40 | AND #$40 | ||
C553 | 85 6F | STA $6F | ||
C555 | 68 | PLA | ||
C556 | 29 DF | AND #$DF | ||
C558 | 30 02 | BMI $C55C | ||
C55A | 09 20 | ORA #$20 | OR the result with $20. | |
CP42 | C55C | 29 27 | AND #$27 | AND the result with $27 and OR it with the value stored in TEMP ($6F) and store the final result back in TEMP. |
C55E | 05 6F | ORA $6F | ||
C560 | 85 6F | STA $6F | ||
C562 | A9 80 | LDA #$80 | Load .A with $80, AND .A with the file pattern type from PATTYP,X ($E7,X), OR the result with the value in TEMP ($6F) , and store the final result back in PATTYP,X. | |
C564 | 35 E7 | AND $E7,X | ||
C566 | 05 6F | ORA $6F | ||
C568 | 95 E7 | STA $E7,X | ||
C56A | B5 E2 | LDA $E2,X | Load .A with the file's drive number from FILDRV,X ($E2,X). AND it with $80 to preserve the default drive bit, OR it with the current drive number, DRVNUM ($7F) and store the result back into FILDRV,X ($E2,X) . | |
C56C | 29 80 | AND #$80 | ||
C56E | 05 7F | ORA $7F | ||
C570 | 95 E2 | STA $E2,X | ||
C572 | B1 94 | LDA ($94),Y | Move the file's first track link from (DIRBUF) ,Y(.Y=1) to FILTRK,X ($0280) and increment .Y. | |
C574 | 9D 80 02 | STA $0280,X | ||
C577 | C8 | INY | ||
C578 | B1 94 | LDA ($94),Y | Move the file's first sector link from (DIRBUF) ,Y(.Y=2) to FILSEC,X ($0285). | |
C57A | 9D 85 02 | STA $0285,X | ||
C57D | AD 58 02 | LDA $0258 | Check the current record length, REC ($0258). If NOT $00, branch to CMPCHK. | |
C580 | D0 07 | BNE $C589 | ||
C582 | A0 15 | LDY #$15 | Set .Y to $15 and move the file entry's record size from (DIRBUF) ,Y to REC. | |
C584 | B1 94 | LDA ($94),Y | ||
C586 | 8D 58 02 | STA $0258 | ||
Check table for unfound files |
||||
CMPCHK | C589 | A9 FF | LDA #$FF | Set all-files-found flag, FOUND ($028F) to $FF. Move the number of files to test from F2CNT ($0278) to F2PTR ($0279). |
C58B | 8D 8F 02 | STA $028F | ||
C58E | AD 78 02 | LDA $0278 | ||
C591 | 8D 79 02 | STA $0279 | ||
CC10 | C594 | CE 79 02 | DEC $0279 | Decrement the file count, F2PTR ($0279). If any files left, branch to CC15. If none left, exit with an RTS. |
C597 | 10 01 | BPL $C59A | ||
C599 | 60 | RTS | ||
CC15 | C59A | AE 79 02 | LDX $0279 | Load .X with the number of the file to test from F2PTR. Load .A with the file's pattern type from PATTYP,X ($E7,X). If file has not been found yet (bit 7 is still set) abort search by branching to CC20. Load .A with the file's first track link from FILTRK,X ($0280, X). If non-zero, the file has been found. so branch back to CC10 to test the next file. |
C59D | B5 E7 | LDA $E7,X | ||
C59F | 30 05 | BMI $C5A6 | ||
C5A1 | BD 80 02 | LDA $0280,X | ||
C5A4 | D0 EE | BNE $C594 | ||
CC20 | C5A6 | A9 00 | LDA #$00 | Load .A with $00 and store it in the all-files-found flag, FOUND ($028F) to indicate that all files have NOT been found and exit with an RTS. |
C5A8 | 8D 8F 02 | STA $028F | ||
C5AB | 60 | RTS | ||
Initiate search of directory |
||||
SRCHST | C5AC | A0 00 | LDY #$00 | Returns with valid entry (DELIND=0) or with the first deleted entry (DELIND=1) Load .Y with $00 and store it in DELSEC. ($0291). Decrement .Y to $FF and store it in the f ound-an-entry flag, ENTFND ($0253) . |
C5AE | 8C 91 02 | STY $0291 | ||
C5B1 | 88 | DEY | ||
C5B2 | 8C 53 02 | STY $0253 | ||
C5B5 | AD 85 FE | LDA $FE85 | To start search at the beginning of the directory, set TRACK ($80) to $12 (#18) (from $FE79) and SECTOR ($81) to $01. Also store $01 in last-sector-in-f ile flag, LSTBUF ($0293) . | |
C5B8 | 85 80 | STA $80 | ||
C5BA | A9 01 | LDA #$01 | ||
C5BC | 85 81 | STA $81 | ||
C5BE | 8D 93 02 | STA $0293 | ||
C5C1 | 20 75 D4 | JSR $D475 | JSR to OPNIRD ($D475) to open the internal channel (SA=16) for a read and to read in the first one or two sectors in the file whose T/S link is given in TRACK ($80) and SECTOR ($81). | |
SR10 | C5C4 | AD 93 02 | LDA $0293 | Test LSTBUF ($0293) to see if we have exhausted the last sector in the directory file. If not (LSTBUF <> $00), branch to SR15. |
C5C7 | D0 01 | BNE $C5CA | ||
C5C9 | 60 | RTS | Exit with an RTS. | |
SR15 | C5CA | A9 07 | LDA #$07 | Set the file count, FILCNT ($0295) to $07 to indicate that there are 8 entries (0-7) left to examine in the buffer. |
C5CC | 8D 95 02 | STA $0295 | ||
C5CF | A9 00 | LDA #$00 | Load .A with $00 and JSR to DRDBYT to read the first byte in the sector (the track link). On return store this value into LSTBUF ($0293). This sets LSTBUF to $00 if there are no more blocks left in in the directory file. | |
C5D1 | 20 F6 D4 | JSR $D4F6 | ||
C5D4 | 8D 93 02 | STA $0293 | ||
SR20 | C5D7 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to set the directory pointer, DIRBUF ($94/5) to the data that was just read into the active buffer, BUFTAB,X ($99/A,X). |
|
||||
C5DA | CE 95 02 | DEC $0295 | Decrement the entry count, FILCNT and load .Y with $00 to begin examination of the first directory entry. | |
C5DD | A0 00 | LDY #$00 | ||
C5DF | B1 94 | LDA ($94),Y | Test the entry's file type in (DIRBUF) ,Y If non-zero, this is NOT a deleted or blank entry so branch to SR30. | |
C5E1 | D0 18 | BNE $C5FB | ||
C5E3 | AD 91 02 | LDA $0291 | Process a scratched or blank entry Test DELSEC ($0291) to see if a deleted entry has already been found. If it has (DELSEC <> $00), branch to SEARCH ( $C617 ) | |
C5E6 | D0 2F | BNE $C617 | ||
C5E8 | 20 3B DE | JSR $DE3B | This is first deleted entry so JSR to CURBLK ($DE3B) to set up the current sector in SECTOR ($81). Save the sector number in DELSEC ($0291) . | |
C5EB | A5 81 | LDA $81 | ||
C5ED | 8D 91 02 | STA $0291 | ||
C5F0 | A5 94 | LDA $94 | Load .A with the low byte of the pointer to the start of this entry (its position in the data buffer) from DIRBUF ($94) . Load .X with the current value of DELIND ($0292). This sets the Z flag to 1 if only valid entries are desired. Store the pointer in .A into DELIND. | |
C5F2 | AE 92 02 | LDX $0292 | ||
C5F5 | 8D 92 02 | STA $0292 | ||
C5F8 | F0 1D | BEQ $C617 | If the Z flag is set, we need valid entries, not deleted ones, so branch to SEARCH to continue the search. | |
C5FA | 60 | RTS | We wanted a deleted entry and we found one so terminate routine with an RTS. | |
SR30 | C5FB | A2 01 | LDX #$01 | We have found a valid entry. Check if we are looking for one by comparing DELIND ($0292) to $01. If not equal, we want a valid entry so branch to SR50. |
C5FD | EC 92 02 | CPX $0292 | ||
C600 | D0 2D | BNE $C62F | ||
C602 | F0 13 | BEQ $C617 | If DELIND = 1, we want a deleted entry, not a valid one, so branch to SEARCH to continue the quest! | |
Re-enter the directory search |
||||
SRRE | C604 | AD 85 FE | LDA $FE85 | Set TRACK ($80) to $12 (#18) from $FE85 Set SECTOR ($81) from the last directory sector used, DIRSEC ($0290) . |
C607 | 85 80 | STA $80 | ||
C609 | AD 90 02 | LDA $0290 | ||
C60C | 85 81 | STA $81 | ||
C60E | 20 75 D4 | JSR $D475 | JSR to OPNIRD ($D475) to open the internal channel (SA=16) for a read and to read in the first one or two sectors in the file whose T/S link is given in TRACK ($80) and SECTOR ($81). | |
C611 | AD 94 02 | LDA $0294 | Load .A with the pointer INDEX ($0294) that points to the start of the last entry we were examining and JSR to SETPNT ($D4C8) to set the DIRPNT ($94/5) to point to the start of the entry. | |
C614 | 20 C8 D4 | JSR $D4C8 | ||
Continue search of entries |
||||
SEARCH | C617 | A9 FF | LDA #$FF | Set found-entry flag, ENTFND ($0253) to $FF. Load .A with number of entries left in the buffer from FILCNT ($0295). If none left, branch to SR40 to get the next buffer of directory entries. |
C619 | 8D 53 02 | STA $0253 | ||
C61C | AD 95 02 | LDA $0295 | ||
C61F | 30 08 | BMI $C629 | ||
C621 | A9 20 | LDA #$20 | There is at least one more entry left in this buffer so load .A with $20 (the # of characters in each entry) and JSR to INCPTR ($D1C6) to set DIRPTR ($94/5) to point to the start of the next entry. JMP to SR20 ($C5D7) to process it. | |
C623 | 20 C6 D1 | JSR $D1C6 | ||
C626 | 4C D7 C5 | JMP $C5D7 | ||
Get next buffer of entries |
||||
SR40 | C629 | 20 4D D4 | JSR $D44D | JSR to NXTBUF ($D44D) to read in the next directory sector and JMP to SR10 to begin processing it. |
C62C | 4C C4 C5 | JMP $C5C4 | ||
SR50 | C62F | A5 94 | LDA $94 | We have found a valid entry so save how far we got and return. Save low byte of the pointer to the entry, from DIRBUF($94) in INDEX ( $0294 ) . |
C631 | 8D 94 02 | STA $0294 | ||
C634 | 20 3B DE | JSR $DE3B | JSR to CURBLK ($DE3B) to store the sector we are checking in SECTOR ($81) . | |
C637 | A5 81 | LDA $81 | Save the current sector number from SECTOR ($81) in DIRSEC ($0290) and RTS. | |
C639 | 8D 90 02 | STA $0290 | ||
C63C | 60 | RTS | ||
Check drive for active diskette, init if neededReturn no drive status. |
||||
AUTOI | C63D | A5 68 | LDA $68 | Test auto-initialization flag, AUTOFG ($68). If AUTOFG <> 0, auto-init is disabled so branch to AUT02 ($C669). |
C63F | D0 28 | BNE $C669 | ||
C641 | A6 7F | LDX $7F | Load .X with the current drive number from DRVNUM ($7F). Test whether the diskette has been changed by doing an LSR on the wr ite-protect-change flag for the current drive, WPSW,X ($1C/D). If the carry flag, C, is clear, the disk has not been changed so branch to AUT02 . | |
C643 | 56 1C | LSR $1C,X | ||
C645 | 90 22 | BCC $C669 | ||
C647 | A9 FF | LDA #$FF | Load .A with $FF. Store this value as the job return code in JOBRTN ($0298) . | |
C649 | 8D 98 02 | STA $0298 | ||
C64C | 20 0E D0 | JSR $D00E | JSR to ITRIAL ($D00E) to do a SEEK to the current drive to determine if a diskette is present. | |
C64F | A0 FF | LDY #$FF | Load .Y with $FF (default to true) . | |
C651 | C9 02 | CMP #$02 | Compare the value in return job code in .A with $02. If equal, NO SYNC was found so branch to AUTO1 to abort. | |
C653 | F0 0A | BEQ $C65F | ||
C655 | C9 03 | CMP #$03 | Compare the value in return job code in .A with $03. If equal, NO HEADER was found so branch to AUTO1 to abort. | |
C657 | F0 06 | BEQ $C65F | ||
C659 | C9 0F | CMP #$0F | Compare the value in return job code in .A with $0F. If equal, NO DRIVE was found so branch to AUTO1 to abort. | |
C65B | F0 02 | BEQ $C65F | ||
C65D | A0 00 | LDY #$00 | Seems OK so load .Y with $00. | |
AUTO1 | C65F | A6 7F | LDX $7F | Load .X with the current drive number DRVNUM ($7F). Transfer the value of .Y into .A ($00 if OK;$FF if BAD) and store in the current drive status, NODRV,X ($FF,X). If status is bad (not $00), branch to AUT02 to abort. |
C661 | 98 | TYA | ||
C662 | 95 FF | STA $FF,X | ||
C664 | D0 03 | BNE $C669 | ||
C666 | 20 42 D0 | JSR $D042 | JSR to INITDR ($D042) to initialize the current drive. | |
AUTO2 | C669 | A6 7F | LDX $7F | Load .A with the current no-drive status and terminate routine with an RTS.
|
C66B | B5 FF | LDA $FF,X | ||
C66D | 60 | RTS | ||
Transfer filename from CMD to buffer |
||||
TRNAME | C66E | 48 | PHA | On entry, .A=string size; .X=starting index in command string; .Y=buffer # Save .A (string size) on the stack. |
C66F | 20 A6 C6 | JSR $C6A6 | JSR to FNDLMT ($C6A6) to find the limit of the string in the command buffer that is pointed to by .X. | |
C672 | 20 88 C6 | JSR $C688 | JSR to TRCMBF ($C688) to transfer the command buffer contents from .X to LIMIT to the data buffer whose number is in .Y | |
C675 | 68 | PLA | Restore the string size into .A from the stack. Set the carry flag and subtract the maximum string size, STRSIZ ($024B) . | |
C676 | 38 | SEC | ||
C677 | ED 4B 02 | SBC $024B | ||
C67A | AA | TAX | Transfer the result from .A to .X. If the result is or negative, the string does not need padding so branch to TN20. | |
C67B | F0 0A | BEQ $C687 | ||
C67D | 90 08 | BCC $C687 | ||
C67F | A9 A0 | LDA #$A0 | String is short and needs to be padded so load .A with $A0 . | |
TN10 | C681 | 91 94 | STA ($94),Y | Loop to pad the string in the directory buffer with .X $A0 ' s. |
C683 | C8 | INY | ||
C684 | CA | DEX | ||
C685 | D0 FA | BNE $C681 | ||
TN20 | C687 | 60 | RTS | Terminate routine with an RTS. |
Transfer CMD buffer to another buffer |
||||
TRCMBF | C688 | 98 | TYA | .X=index to first chr in command buffer LIMIT=index to last chr+1 in CMD buffer . Y=buffer#. Uses current buffer pointer. Multiply .Y by 2 (TYA; ASL; TAY) . |
C689 | 0A | ASL | ||
C68A | A8 | TAY | ||
C68B | B9 99 00 | LDA $0099,Y | Use current buffer pointers, BUFTAB,Y ($99/A,Y) to set the directory buffer pointers, DIRBUF ($94/5). Zero .Y (index into directory buffer) | |
C68E | 85 94 | STA $94 | ||
C690 | B9 9A 00 | LDA $009A,Y | ||
C693 | 85 95 | STA $95 | ||
C695 | A0 00 | LDY #$00 | ||
TR10 | C697 | BD 00 02 | LDA $0200,X | Move character from CMDBUF,X ($0200, X) to (DIRBUF) ,Y ; ($94) ,Y. |
C69A | 91 94 | STA ($94),Y | ||
C69C | C8 | INY | Increment .Y. If .Y equals $00, branch to TR20 to abort. | |
C69D | F0 06 | BEQ $C6A5 | ||
C69F | E8 | INX | Increment .X. If .X < LIMIT ($0276) branch back to TRIO to do next character | |
C6A0 | EC 76 02 | CPX $0276 | ||
C6A3 | 90 F2 | BCC $C697 | ||
TR20 | C6A5 | 60 | RTS | Terminate routine with an RTS. |
Find the limit (end) of the string in the command buffer that is pointed to by X |
||||
FNDLMT | C6A6 | A9 00 | LDA #$00 | Zero the string size, STRSIZ ($024B). Transfer the starting pointer from .X to .A and save it on the stack. |
C6A8 | 8D 4B 02 | STA $024B | ||
C6AB | 8A | TXA | ||
C6AC | 48 | PHA | ||
FL05 | C6AD | BD 00 02 | LDA $0200,X | Load .A with the Xth command string character, CMDBUF,X ($0200, X). |
C6B0 | C9 2C | CMP #$2C | Compare the character to a ". ". If they match, we're at the end. Branch to FL10. | |
C6B2 | F0 14 | BEQ $C6C8 | ||
C6B4 | C9 3D | CMP #$3D | Compare the character to a "=". If they match, we* re at the end. Branch to FL10. | |
C6B6 | F0 10 | BEQ $C6C8 | ||
C6B8 | EE 4B 02 | INC $024B | Increment STRSIZ ($024B) and .X | |
C6BB | E8 | INX | ||
C6BC | A9 0F | LDA #$0F | Check if the string size, STRSIZ, has reached the maximum size of $0F (#15) . If it has, branch to FL10 to quit. | |
C6BE | CD 4B 02 | CMP $024B | ||
C6C1 | 90 05 | BCC $C6C8 | ||
C6C3 | EC 74 02 | CPX $0274 | Compare .X to the pointer to the end of the command string, CMDSIZ ($0274). If we're NOT at the end. Branch to FL05. | |
C6C6 | 90 E5 | BCC $C6AD | ||
FL10 | C6C8 | 8E 76 02 | STX $0276 | Store the .X value (the last character plus 1) into LIMIT ($0276). |
C6CB | 68 | PLA | Pull the original .X value off the stack into .A and transfer it to .X | |
C6CC | AA | TAX | ||
C6CD | 60 | RTS | Terminate routine with an RTS. | |
Get file entry from directory (called by STDIR and GETDIR) |
||||
GETNAM | C6CE | A5 83 | LDA $83 | Save secondary address, SA ($83) on the stack. |
C6D0 | 48 | PHA | ||
C6D1 | A5 82 | LDA $82 | Save the current channel*, LINDX ($82) on the stack. | |
C6D3 | 48 | PHA | ||
C6D4 | 20 DE C6 | JSR $C6DE | JSR to GNSUB ($C6DE) to get a directory entry using the internal read channel SA=$11(#17)\ | |
C6D7 | 68 | PLA | Pull the original SA and LINDX values from the stack and reset these variables | |
C6D8 | 85 82 | STA $82 | ||
C6DA | 68 | PLA | ||
C6DB | 85 83 | STA $83 | ||
C6DD | 60 | RTS | Terminate the routine with an RTS. | |
Get file entry subroutine |
||||
GNSUB | C6DE | A9 11 | LDA #$11 | Set current secondary address, SA ($83) to $11 (internal read secondary address) |
C6E0 | 85 83 | STA $83 | ||
C6E2 | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. | |
C6E5 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to set the directory buffer pointer, DIRBUF ($94/5) from the pointer to the currently active buffer using values from BUFTAB ($30/1) . | |
C6E8 | AD 53 02 | LDA $0253 | Test the found entry flag, ENTFLG ($0253 ) to see if there are more files. If there are more (ENTFLG > 127), branch to GN05. | |
C6EB | 10 0A | BPL $C6F7 | ||
C6ED | AD 8D 02 | LDA $028D | No more entries so test DRVFLG ($028D) to see if we have the other drive to do. If DRVFLG <> 0, branch to GN050 to do the other drive. GN0 5 | |
C6F0 | D0 0A | BNE $C6FC | ||
C6F2 | 20 06 C8 | JSR $C806 | JSR to MSGFRE ($C806) to send the BLOCKS FREE message. | |
C6F5 | 18 | CLC | Clear carry bit and exit with an RTS. | |
C6F6 | 60 | RTS | ||
GN05 | C6F7 | AD 8D 02 | LDA $028D | Test drive flag, DRVFLG ($028D). If $00, branch to GN10. |
C6FA | F0 1F | BEQ $C71B | ||
GN050 | C6FC | CE 8D 02 | DEC $028D | Decrement drive flag, DRVFLG ($028D). If not $00, branch to GN0 51 to do a new directory. |
C6FF | D0 0D | BNE $C70E | ||
C701 | CE 8D 02 | DEC $028D | Decrement drive flag, DRVFLG ($028D) . | |
C704 | 20 8F C3 | JSR $C38F | JSR to TOGDRV ($C38F) to switch drives. | |
C707 | 20 06 C8 | JSR $C806 | JSR to MSGFRE ($C806) to send the BLOCKS FREE message. | |
C70A | 38 | SEC | Set the carry flag and exit with a JMP to TOGDRV ($C3 F) to switch drives. 8 | |
C70B | 4C 8F C3 | JMP $C38F | ||
GN051 | C70E | A9 00 | LDA #$00 | Load .A with $0and zero the hi byte of the number of blocks counter, NBTEMP+1 ($0273) and thedrive flag DRVFLG ($028D) |
C710 | 8D 73 02 | STA $0273 | ||
C713 | 8D 8D 02 | STA $028D | ||
C716 | 20 B7 C7 | JSR $C7B7 | JSR to NEWDIR ($C7B7) to begin a new directory listing. | |
C719 | 38 | SEC | Set the carry flag and exit with an RTS. | |
C71A | 60 | RTS | ||
GN10 | C71B | A2 18 | LDX #$18 | Load .X with $18 (#24), the length of an entry in a directory listing e.g.' 114 "PROGRAM FILENAME" PRG |
C71D | A0 1D | LDY #$1D | Load .Y with $1D, the position of the hi byte of the # of blocks in the file, | |
C71F | B1 94 | LDA ($94),Y | Load .A with the hi byte of the # of blocks in the file. Store this into the hi byte of the block counter, NBTEMP+1 ($0273). If zero, branch to GN12. | |
C721 | 8D 73 02 | STA $0273 | ||
C724 | F0 02 | BEQ $C728 | ||
C726 | A2 16 | LDX #$16 | Load .X with $16 (#22) the directory length less 2. | |
GN12 | C728 | 88 | DEY | Decrement Y so it points to the position of the lo byte of the # of blocks in the file. |
C729 | B1 94 | LDA ($94),Y | Load .A with the lo byte of the # of blocks in the file. Store this into lo byte of the block counter, NBTEMP the ($0272). | |
C72B | 8D 72 02 | STA $0272 | ||
C72E | E0 16 | CPX #$16 | Compare .X to $16 (#22) the directory length less 2. If they are equal, branch to GN14. | |
C730 | F0 0A | BEQ $C73C | ||
C732 | C9 0A | CMP #$0A | Compare .A (the lo byte of the blocks) with $0A (#10). If .A<10 branch to GN14 | |
C734 | 90 06 | BCC $C73C | ||
C736 | CA | DEX | Decrement .X (we will need less padding since # of blocks is at least 2 digits. | |
C737 | C9 64 | CMP #$64 | Compare .A (the lo byte of the blocks) with $64 (#100). If A<100 branch to GN14 | |
C739 | 90 01 | BCC $C73C | ||
C73B | CA | DEX | Decrement .X (we will need less padding since # of blocks is at least 3 digits). | |
GN14 | C73C | 20 AC C7 | JSR $C7AC | JSR to BLKNB ($C7AC) to clear the name buffer for the next entry. On return Y=0 |
C73F | B1 94 | LDA ($94),Y | Load .A with the file type from the directory buffer (DIRBUF) ,Y and save the file type onto the stack. | |
C741 | 48 | PHA | ||
C742 | 0A | ASL | Do an ASL of the value in .A to set the carry bit if this is a valid file that has not been closed, (see BCS $C764) | |
C743 | 10 05 | BPL $C74A | If .A<128, branch to GN15. NOTE: The branch at $C742 and the code following is what produces the PRG<. SEQ< , etc. file types. Note that these file types are LOCKED and can't be SCRATCHED! The locking and unlocking of files is NOT supported by any Commodore DOS. To lock a file, change its file type in its directory entry from $80, $81, etc to $C0, $C1, etc. Reverse the process for unlocking | |
C745 | A9 3C | LDA #$3C | Load .A with a $3C (a "<"). | |
C747 | 9D B2 02 | STA $02B2,X | Store this value into the name buffer NAMBUF+1,X ($02B1,X) . | |
GN15 | C74A | 68 | PLA | Pull the file type off the stack and AND it with $0F to mask off the higher bits. Transfer it to .Y to use as an index. |
C74B | 29 0F | AND #$0F | ||
C74D | A8 | TAY | ||
C74E | B9 C5 FE | LDA $FEC5,Y | Move last character in file type name from TP2LST,Y ($FEC5,Y) to the name buffer, NAMBUF,X ($02B1,X). | |
C751 | 9D B1 02 | STA $02B1,X | ||
C754 | CA | DEX | Decrement .X | |
C755 | B9 C0 FE | LDA $FEC0,Y | Move middle character in file type name from TP1LST,Y ($FEC0,Y) to the name buffer, NAMBUF,X ($02B1,X). | |
C758 | 9D B1 02 | STA $02B1,X | ||
C75B | CA | DEX | Decrement .X | |
C75C | B9 BB FE | LDA $FEBB,Y | Move first character in file type name from TYPLST,Y ($FEBB,Y) to the name buffer, NAMBUF,X ($02B1,X). | |
C75F | 9D B1 02 | STA $02B1,X | ||
C762 | CA | DEX | Decrement .X twice | |
C763 | CA | DEX | ||
C764 | B0 05 | BCS $C76B | If carry bit is set (indicates valid entry; see $C742) branch to GN20. | |
C766 | A9 2A | LDA #$2A | Load .A with $2A (a "*") to indicate an improperly closed file. | |
C768 | 9D B2 02 | STA $02B2,X | Store the "*" in NAMBUF+1,X ($02B1,X). | |
GN20 | C76B | A9 A0 | LDA #$A0 | Store a shifted space, $A0 in the buffer (between name & type) and decrement .X |
C76D | 9D B1 02 | STA $02B1,X | ||
C770 | CA | DEX | ||
C771 | A0 12 | LDY #$12 | Load .Y with $12 (#18) so it points to the end of the name in the dir buffer. | |
GN22 | C773 | B1 94 | LDA ($94),Y | Loop to transfer the 16 characters in the file name from the directory buffer to the name buffer. |
C775 | 9D B1 02 | STA $02B1,X | ||
C778 | CA | DEX | ||
C779 | 88 | DEY | ||
C77A | C0 03 | CPY #$03 | ||
C77C | B0 F5 | BCS $C773 | ||
C77E | A9 22 | LDA #$22 | Load .A with $22 (a ' " ' ) | |
C780 | 9D B1 02 | STA $02B1,X | Store quotation mark before the name. | |
GN30 | C783 | E8 | INX | Loop to scan up the name looking for a quote mark($22) or a shifted space ($AO). When either character is found or the end of the name is reached, store a $22 (quote mark) at that location. Then AND any remaining characters in the name with $7F to clear bit 7 for each one. |
C784 | E0 20 | CPX #$20 | ||
C786 | B0 0B | BCS $C793 | ||
C788 | BD B1 02 | LDA $02B1,X | ||
C78B | C9 22 | CMP #$22 | ||
C78D | F0 04 | BEQ $C793 | ||
C78F | C9 A0 | CMP #$A0 | ||
C791 | D0 F0 | BNE $C783 | ||
C793 | A9 22 | LDA #$22 | ||
C795 | 9D B1 02 | STA $02B1,X | ||
C798 | E8 | INX | ||
C799 | E0 20 | CPX #$20 | ||
C79B | B0 0A | BCS $C7A7 | ||
C79D | A9 7F | LDA #$7F | ||
C79F | 3D B1 02 | AND $02B1,X | ||
C7A2 | 9D B1 02 | STA $02B1,X | ||
C7A5 | 10 F1 | BPL $C798 | ||
GN40 | C7A7 | 20 B5 C4 | JSR $C4B5 | JSR to FNDFIL ($C4B5) to find the next entry. On return, set the carry bit. |
C7AA | 38 | SEC | ||
GN45 | C7AB | 60 | RTS | Terminate the routine with an RTS. |
Blank the name buffer |
||||
BLKNB | C7AC | A0 1B | LDY #$1B | Load .Y with $1B, the length of the name buffer, and .A with $20, a space. |
C7AE | A9 20 | LDA #$20 | ||
BLKNB1 | C7B0 | 99 B0 02 | STA $02B0,Y | Loop to store $20 's in all locations in the name buffer, NAMBUF ($02B1-CB) |
C7B3 | 88 | DEY | ||
C7B4 | D0 FA | BNE $C7B0 | ||
C7B6 | 60 | RTS | Terminate the routine with an RTS. | |
New directory in listing |
||||
NEWDIR | C7B7 | 20 19 F1 | JSR $F119 | JSR to BAM2X ($F119) to set BAM pointer in buffer 0/1 tables and leave in .X |
C7BA | 20 DF F0 | JSR $F0DF | JSR to REDBAM ($F0DF) to read in the BAM to $0700-FF if not already present. | |
C7BD | 20 AC C7 | JSR $C7AC | JSR to BLKNB ($C7AC) to blank the name buffer, NAMBUF ($02B1-CB). | |
C7C0 | A9 FF | LDA #$FF | Set TEMP ($6F) to $FF | |
C7C2 | 85 6F | STA $6F | ||
C7C4 | A6 7F | LDX $7F | Set NBTEMP ($0272) to the current drive number from DRVNUM ($7F) | |
C7C6 | 8E 72 02 | STX $0272 | ||
C7C9 | A9 00 | LDA #$00 | Set NBTEMP+1 ($0273) to $00 | |
C7CB | 8D 73 02 | STA $0273 | ||
C7CE | A6 F9 | LDX $F9 | Load .X with the position of the read BAM job in the queue from JOBNUM ($F9) . | |
C7D0 | BD E0 FE | LDA $FEE0,X | Set high byte of the pointer to the directory buffer, DIRBUF ($94/5) using a value (3,4,5,6,7,7) from BUFIND,X ( $FEE0 ) | |
C7D3 | 85 95 | STA $95 | ||
C7D5 | AD 88 FE | LDA $FE88 | Set low byte of the pointer to the directory buffer, DIRBUF ($94/5) using the value ($90) from DSKNAM ($FE88). DIRBUF now points to the start of the disk name in the BAM buffer ($0x90) | |
C7D8 | 85 94 | STA $94 | ||
C7DA | A0 16 | LDY #$16 | Load .Y with $16 (#22). the name length. | |
ND10 | C7DC | B1 94 | LDA ($94),Y | Load .A with character, (DIRBUF) ,Y and test if it is a shifted blank ($A0) . If not, branch to ND20. |
C7DE | C9 A0 | CMP #$A0 | ||
C7E0 | D0 0B | BNE $C7ED | ||
C7E2 | A9 31 | LDA #$31 | Since it is not a shifted blank, load .A with a $31 (ASCII "1") for version #1. | |
C7E4 | 2C | BYTE $2C here causes branch to ND20. | ||
ND15 | C7E5 | B1 94 | LDA ($94),Y | Load .A with character, (DIRBUF) ,Y and test if it is a shifted blank ($A0) . If not, branch to ND20. |
C7E7 | C9 A0 | CMP #$A0 | ||
C7E9 | D0 02 | BNE $C7ED | ||
C7EB | A9 20 | LDA #$20 | Since it is not a shifted blank, load .A with a $20 (ASCII space). | |
ND20 | C7ED | 99 B3 02 | STA $02B3,Y | Store the character in .A into the name buffer, NAMBUF+2,Y ($02B3,Y). |
C7F0 | 88 | DEY | ||
C7F1 | 10 F2 | BPL $C7E5 | If more characters left (.Y>=0) branch back to ND15. | |
C7F3 | A9 12 | LDA #$12 | Store a $12 (RVS on) in NAMBUF ($02B1) | |
C7F5 | 8D B1 02 | STA $02B1 | ||
C7F8 | A9 22 | LDA #$22 | Store a $22 (quote) in NAMBUF+1 ($02B2) | |
C7FA | 8D B2 02 | STA $02B2 | ||
C7FD | 8D C3 02 | STA $02C3 | Store a $22 (quote) in NAMBUF+18 ($02C3 ) | |
C800 | A9 20 | LDA #$20 | Store a $20 (space) in NAMBUF+19 ($02C4) | |
C802 | 8D C4 02 | STA $02C4 | ||
C805 | 60 | RTS | Terminate routine with an RTS. | |
Set up message "BLOCKS FREE" |
||||
MSGFRE | C806 | 20 AC C7 | JSR $C7AC | JSR to BLKNB ($C7AC) to clear the name buffer. |
C809 | A0 0B | LDY #$0B | Load .Y with $0B (message length -1) . | |
C80B | B9 17 C8 | LDA $C817,Y | Loop using .Y as index to move message from FREMSG, Y ($C817,Y) to NAMBUF, Y ($02B1,Y) . | |
C80E | 99 B1 02 | STA $02B1,Y | ||
C811 | 88 | DEY | ||
C812 | 10 F7 | BPL $C80B | ||
C814 | 4C 4D EF | JMP $EF4D | Terminate routine with a JMP to NUMFRE ($EF4D) to calculate the number free. | |
FREMSG | C817 | 42 4C 4F 43 4B 53 20 46 52 45 45 2E | Message "BLOCKS FREE" | |
Scratch one or more files |
||||
SCRTCH | C823 | 20 98 C3 | JSR $C398 | JSR to FS1SET ($C398) to set up for one file stream. |
C826 | 20 20 C3 | JSR $C320 | JSR to ALLDRS ($C320) to all drives needed based on F2CNT. | |
C829 | 20 CA C3 | JSR $C3CA | JSR to OPTSCH ($C3CA) to determine best sequence of drives to use. | |
C82C | A9 00 | LDA #$00 | Zero file counter, R0 ($86) | |
C82E | 85 86 | STA $86 | ||
C830 | 20 9D C4 | JSR $C49D | JSR to FFST ($C49D) to find the first directory entry. If not successful, branch to SC30. | |
C833 | 30 3D | BMI $C872 | ||
|
||||
SC15 | C835 | 20 B7 DD | JSR $DDB7 | JSR to TSTCHN ($DDB7) to test for active files from index table. |
C838 | 90 33 | BCC $C86D | If file active (carry clear). branch to SC25. | |
|
||||
C83A | A0 00 | LDY #$00 | Load .Y with $00. | |
C83C | B1 94 | LDA ($94),Y | Load .A with file type from (DIRBUF) ,Y ($94, Y). | |
C83E | 29 40 | AND #$40 | AND the file type with $40 to test if it is a locked file (bit 6 of filetype set) | |
C840 | D0 2B | BNE $C86D | If a locked file, branch to SC25. | |
C842 | 20 B6 C8 | JSR $C8B6 | JSR to DELDIR ($C8B6) to delete the directory entry. Stores $00 as the file type and rewrite the sector on disk. | |
C845 | A0 13 | LDY #$13 | Load .Y with $13 (#19) . | |
C847 | B1 94 | LDA ($94),Y | Test whether this is a relative file by loading .A with 19th character of the entry (the track of the side-sector pointer for a REL file) from (DIRBUF) ,Y | |
C849 | F0 0A | BEQ $C855 | If $00, not a REL file so branch to SC17 | |
C84B | 85 80 | STA $80 | Store trackpointer into TRACK ($80) . | |
C84D | C8 | INY | Increment Y and move sector pointer from (DIRBUF) ,Y into SECTOR ($81). | |
C84E | B1 94 | LDA ($94),Y | ||
C850 | 85 81 | STA $81 | ||
C852 | 20 7D C8 | JSR $C87D | JSR to DELFIL ($C87D) to free the side sectors by updating and writing the BAM | |
|
||||
SC17 | C855 | AE 53 02 | LDX $0253 | Load .X with the directory entry counter ENTFND ($0253) and .A with $20. |
C858 | A9 20 | LDA #$20 | ||
C85A | 35 E7 | AND $E7,X | AND .A with the file pattern type in PATTYP,X ($E7,X) to check if this is an opened but unclosed file. | |
C85C | D0 0D | BNE $C86B | If unclosed file, branch to SC20. | |
C85E | BD 80 02 | LDA $0280,X | Move initial track link from FILTRK,X ($0280, X) into TRACK ($80). | |
C861 | 85 80 | STA $80 | ||
C863 | BD 85 02 | LDA $0285,X | Move initial sector link from FILSEC,X ($0285, X) into SECTOR ($81). | |
C866 | 85 81 | STA $81 | ||
C868 | 20 7D C8 | JSR $C87D | JSR to DELFIL ($C87D) to free the file blocks by updating and writing the BAM | |
SC20 | C86B | E6 86 | INC $86 | Increment the file counter, R0 ($86). |
SC25 | C86D | 20 8B C4 | JSR $C48B | JSR to FFRE ($C48B) to match the next filename in the command string. |
C870 | 10 C3 | BPL $C835 | If a match found, branch to SC15 | |
SC30 | C872 | A5 86 | LDA $86 | All done. Store number of files that have been scratched, R0 ($86) into TRACK ($80) |
C874 | 85 80 | STA $80 | ||
C876 | A9 01 | LDA #$01 | Load .A with $01 and .Y with $00 | |
C878 | A0 00 | LDY #$00 | ||
C87A | 4C A3 C1 | JMP $C1A3 | Exit with a JMP to SCREND ($C1A3) | |
Delete file by links |
||||
DELFIL | C87D | 20 5F EF | JSR $EF5F | JSR to FRETS ($EF5F) to mark the first file block as free in the BAM. |
C880 | 20 75 D4 | JSR $D475 | JSR to OPNIRD ($D475) to open the internal read channel (SA=17) and read in the first one or two blocks. | |
C883 | 20 19 F1 | JSR $F119 | JSR to BAM2X ($F119) to set BAM pointers in the buffer tables | |
C886 | B5 A7 | LDA $A7,X | Load .A from BUF0,X ($A7,X) and compare it to $FF to see if buffer inactive. If inactive (.A=$FF, branch to DEL2 ) Load write BAM flag, WBAM ($02F9). OR it, with $40 to set bit6 and store it back in WBAM to indicate both buffers active. | |
C888 | C9 FF | CMP #$FF | ||
C88A | F0 08 | BEQ $C894 | ||
C88C | AD F9 02 | LDA $02F9 | ||
C88F | 09 40 | ORA #$40 | ||
C891 | 8D F9 02 | STA $02F9 | ||
DEL2 | C894 | A9 00 | LDA #$00 | Zero .A and JSR to SETPNT ( $D4C8 ) to set pointers to the currently active buffer. |
C896 | 20 C8 D4 | JSR $D4C8 | ||
C899 | 20 56 D1 | JSR $D156 | JSR to RDBYT ($D156) to direct read one byte (the track link from the buffer) | |
C89C | 85 80 | STA $80 | Store track link into TRACK ($80) | |
C89E | 20 56 D1 | JSR $D156 | JSR to RDBYT ($D156) to direct read one byte (the sector link from the buffer) | |
C8A1 | 85 81 | STA $81 | Store sector link into SECTOR ($81) | |
C8A3 | A5 80 | LDA $80 | Test track link. If not $00 (not final sector in this file). branch to DELI | |
C8A5 | D0 06 | BNE $C8AD | ||
C8A7 | 20 F4 EE | JSR $EEF4 | JSR to MAPOUT ($EEF4) write out the BAM. | |
C8AA | 4C 27 D2 | JMP $D227 | Exit with a JMP to FRECHN ($D227) to free the internal read channel. | |
DEL1 | C8AD | 20 5F EF | JSR $EF5F | JSR to FRETS ($EF5F) to de-allocate (free) specified in TRACK ($80) & SECTOR ($81) in the BAM. |
C8B0 | 20 4D D4 | JSR $D44D | JSR to NXTBUF ($D44D) to read in the next block in the file (use T/S link) . | |
C8B3 | 4C 94 C8 | JMP $C894 | JMP to DEL2 to de-allocate the new block | |
Delete the directory entry |
||||
DELDIR | C8B6 | A0 00 | LDY #$00 | Load .Y with $00 (will point to the 0th character in the entry; the file type) . |
C8B8 | 98 | TYA | Set the file type, (DIRBUF) ,Y; ($94) ,Y to $00 to indicate a scratched file. | |
C8B9 | 91 94 | STA ($94),Y | ||
C8BB | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write out the directory block. | |
C8BE | 4C 99 D5 | JMP $D599 | Exit with a JMP to WATJOB ($D599) to wait for the write job to be completed. | |
Duplicate diskNot available on the 1541 |
||||
C8C1 | A9 31 | LDA #$31 | Load .A with a $31 to indicate a bad command and JMP to CMDERR ($C1C8). | |
C8C3 | 4C C8 C1 | JMP $C1C8 | ||
Format diskette routineThis routine sets up a jump instruction in buffer that points to the code used by the disk controller to do the formatting. It then puts an exectute job code in the job queue. The routine then waits while the disk controller actually does the formatting. |
||||
FORMAT | C8C6 | A9 4C | LDA #$4C | Store JMP $FABB ( $4C. $BB, $FA) at the start of buffer ($0600/1/2). |
C8C8 | 8D 00 06 | STA $0600 | ||
C8CB | A9 C7 | LDA #$C7 | ||
C8CD | 8D 01 06 | STA $0601 | ||
C8D0 | A9 FA | LDA #$FA | ||
C8D2 | 8D 02 06 | STA $0602 | ||
C8D5 | A9 03 | LDA #$03 | Load .A with $03 and JSR to SETH ($D6D3) to set up header of active buffer to the values in TRACK ($80) and SECTOR ($81) . | |
C8D7 | 20 D3 D6 | JSR $D6D3 | ||
C8DA | A5 7F | LDA $7F | Load drive number, DRVNUM ($7F). EOR it with $E0 (execute job code) and store the result in the job queue ($0003) . | |
C8DC | 09 E0 | ORA #$E0 | ||
C8DE | 85 03 | STA $03 | ||
FMT105 | C8E0 | A5 03 | LDA $03 | Load .A from the job queue ($0003). If .A > 127, the job has not been finished yet so branch back to FMT105. |
C8E2 | 30 FC | BMI $C8E0 | ||
C8E4 | C9 02 | CMP #$02 | Compare .A with $02. if .A < 2, the job was completed OK so branch to FMT110. | |
C8E6 | 90 07 | BCC $C8EF | ||
C8E8 | A9 03 | LDA #$03 | Error code returned by disk controller indicates a problem so load .A with $03 and .X with $00 and exit with a JMP to ERROR ($E60A). | |
C8EA | A2 00 | LDX #$00 | ||
C8EC | 4C 0A E6 | JMP $E60A | ||
FMT110 | C8EF | 60 | RTS | Job completed satisfactorily so exit with an RTS. |
Copy disk files routine |
||||
DSKCPY | C8F0 | A9 E0 | LDA #$E0 | Store $E0 in BUFUSE ($024F) to kill the BAM buffer. |
C8F2 | 8D 4F 02 | STA $024F | ||
C8F5 | 20 D1 F0 | JSR $F0D1 | JSR to CLNBAM ($F0D1) to settrack and sector links in BAM to $00. | |
C8F8 | 20 19 F1 | JSR $F119 | JSR to BAM2X ($F119) to return the BAM LINDX in .X. | |
C8FB | A9 FF | LDA #$FF | Store $FF in BUF0,X ($A7,X) to mark the BAM as out-of-memory . | |
C8FD | 95 A7 | STA $A7,X | ||
C8FF | A9 0F | LDA #$0F | Store $0F in LINUSE ($0256) to free all LINDXs. | |
C901 | 8D 56 02 | STA $0256 | ||
C904 | 20 E5 C1 | JSR $C1E5 | JSR to PRSCLN ($C1E5) to parse the command string and find the colon, | |
C907 | D0 03 | BNE $C90C | If colon found (Z flag =0) ,branch to DX0000. | |
C909 | 4C C1 C8 | JMP $C8C1 | Colon not found in command string so command must be CX=Y. This command is not supported on the 1541 soexit with a JMP to DUPLCT ($C8C1). | |
DX0000 | C90C | 20 F8 C1 | JSR $C1F8 | JSR to TC30 ($C1F8) to parse the command string. |
DX0005 | C90F | 20 20 C3 | JSR $C320 | JSR to ALLDRS ($C320) to put the drive numbers into the file table. |
C912 | AD 8B 02 | LDA $028B | Load .A with the command pattern image as determined by the parser from IMAGE ($028B). AND the image with %01010101 ($55). If the result is not $00, the command must be a concatenate or normal copy so branch to DX0020. | |
C915 | 29 55 | AND #$55 | ||
C917 | D0 0F | BNE $C928 | ||
C919 | AE 7A 02 | LDX $027A | Check for pattern matching in the name (as in cl:game=0 :*) by loading .X from FILTBL ($027A) and then loading .A from the command string, CMDBUF,X ($0200, X). | |
C91C | BD 00 02 | LDA $0200,X | ||
C91F | C9 2A | CMP #$2A | The value in .A is compared to $2A ("*") If there is no match, there is no wild so branch to DX0020. | |
C921 | D0 05 | BNE $C928 | ||
DX0010 | C923 | A9 30 | LDA #$30 | Load .A with the $30 to indicate a syntax error and JMP to CMDERR ($C1C8) . |
C925 | 4C C8 C1 | JMP $C1C8 | ||
DX0020 | C928 | AD 8B 02 | LDA $028B | Load .A with the command pattern image as determined by the parser from IMAGE ($028B). AND the image with %11011001 ($D9). If the result is not $00, the syntax is bad so branch to DX0010 and abort. |
C92B | 29 D9 | AND #$D9 | ||
C92D | D0 F4 | BNE $C923 | ||
C92F | 4C 52 C9 | JMP $C952 | JMP to COPY ($C952) to do the file copy, syntax error and JMP to CMDERR ($C1C8). | |
PUPS1 | C932 | A9 00 | LDA #$00 | Subroutine used to set up for copying entire disk (C1=0). Not used on 1541. |
C934 | 8D 58 02 | STA $0258 | ||
C937 | 8D 8C 02 | STA $028C | ||
C93A | 8D 80 02 | STA $0280 | ||
C93D | 8D 81 02 | STA $0281 | ||
C940 | A5 E3 | LDA $E3 | ||
C942 | 29 01 | AND #$01 | ||
C944 | 85 7F | STA $7F | ||
C946 | 09 01 | ORA #$01 | ||
C948 | 8D 91 02 | STA $0291 | ||
C94B | AD 7B 02 | LDA $027B | ||
C94E | 8D 7A 02 | STA $027A | ||
C951 | 60 | RTS | ||
Copy file(s) to one file |
||||
COPY | C952 | 20 4F C4 | JSR $C44F | JSR to LOOKUP ($C44F) to look up the file(s) listed in the command string in the directory. |
C955 | AD 78 02 | LDA $0278 | Load .A with the number of filenames in the command string from F2CNT($0278) and compare it with $03. If fewer than three files, this is not a concatenate so branch to COP10 ($C9A1). | |
C958 | C9 03 | CMP #$03 | ||
C95A | 90 45 | BCC $C9A1 | ||
C95C | A5 E2 | LDA $E2 | Load .A with the first file drive number from FILDRV ($E2) and compare it to the second drive number in FILDRV+1 ($E3) . If not equal, this is not a concatenate so branch to COP10 ($C9A1). | |
C95E | C5 E3 | CMP $E3 | ||
C960 | D0 3F | BNE $C9A1 | ||
C962 | A5 DD | LDA $DD | Load .A with the index to the first file entry from ENTIND ($DD) and compare it to the second file's index in ENTIND+1 ($DE). If not equal, this is not a concatenate so branch to COP10 ($C9A1) . | |
C964 | C5 DE | CMP $DE | ||
C966 | D0 39 | BNE $C9A1 | ||
C968 | A5 D8 | LDA $D8 | Load .A with the first file's sector link from ENTSEC ($D8) and compare it to the second file's link in ENTSEC+1 ($D9). If not equal, this is not a concatenate so branch to COP10 ($C9A1) . | |
C96A | C5 D9 | CMP $D9 | ||
C96C | D0 33 | BNE $C9A1 | ||
Concatenate files |
||||
C96E | 20 CC CA | JSR $CACC | JSR to CHKIN ($CACC) to check if input file exists. | |
C971 | A9 01 | LDA #$01 | Set F2PTR ($0279) to $01 and JSR to OPIRFL ($C9FA) to open the internal read channel, read in the directory file, and locate the named file | |
C973 | 8D 79 02 | STA $0279 | ||
C976 | 20 FA C9 | JSR $C9FA | ||
C979 | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to determine the file type. If $00, a scratched file so branch to COP01 (filetype mismatch) . | |
C97C | F0 04 | BEQ $C982 | ||
C97E | C9 02 | CMP #$02 | Compare the file typeto $02. If not equal, it is not a deleted program file so branch to COP05 tocontinue. | |
C980 | D0 05 | BNE $C987 | ||
COP01 | C982 | A9 64 | LDA #$64 | Bad file name. Load .A with $64 to indicate a file type mismatch and JSR to CMDERR ($C1C8). |
C984 | 20 C8 C1 | JSR $C1C8 | ||
COP05 | C987 | A9 12 | LDA #$12 | Set secondary address, SA ($83) to $12 (#18, the internal write channel) |
C989 | 85 83 | STA $83 | ||
C98B | AD 3C 02 | LDA $023C | Move the active buffer pointer from LINTAB+IRSA ($023C) to LINTAB+IWSA ($023D) . | |
C98E | 8D 3D 02 | STA $023D | ||
C991 | A9 FF | LDA #$FF | Deactivate the internal read channel by storing $FF in LINTAB+IRSA ($023C) . | |
C993 | 8D 3C 02 | STA $023C | ||
C996 | 20 2A DA | JSR $DA2A | JSR to APPEND ($DA2A) to copy first file | |
C999 | A2 02 | LDX #$02 | Load .X with $02 and JSR to CY10 ($C9B9) to copy second file behind the first. | |
C99B | 20 B9 C9 | JSR $C9B9 | ||
C99E | 4C 94 C1 | JMP $C194 | Exit routine with a JMP to ENDCMD ($C194) | |
Copy file |
||||
COP10 | C9A1 | 20 A7 C9 | JSR $C9A7 | JSR to CY ($C9A7) to do copy. |
C9A4 | 4C 94 C1 | JMP $C194 | Exit routine with a JMP to ENDCMD ($C194) | |
CY | C9A7 | 20 E7 CA | JSR $CAE7 | JSR to CHKIO ($CAE7) to check if file exists. |
C9AA | A5 E2 | LDA $E2 | Get drive number from FILDRV ($E2). AND it with $01 (mask off default bit). and store it in DRVNUM ($7F) . | |
C9AC | 29 01 | AND #$01 | ||
C9AE | 85 7F | STA $7F | ||
C9B0 | 20 86 D4 | JSR $D486 | JSR to OPNIWR ($D486) to open internal write channel. | |
C9B3 | 20 E4 D6 | JSR $D6E4 | JSR to ADDFIL ($D6E4) to add the new file name to the directory and rewrite the directory. | |
C9B6 | AE 77 02 | LDX $0277 | Load .X with pointer from F1CNT ($0277) . | |
CY10 | C9B9 | 8E 79 02 | STX $0279 | Store .X in F2CNT ($0278). |
C9BC | 20 FA C9 | JSR $C9FA | JSR to OPIRFL ($C9FA) to open internal read channel and read in one or two blocks of the directory. | |
C9BF | A9 11 | LDA #$11 | Set secondary address, SA ($83) to $11, to set up the internal read channel. | |
C9C1 | 85 83 | STA $83 | ||
C9C3 | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. | |
C9C6 | 20 25 D1 | JSR $D125 | JSR to TYPFIL (SD125) to determine if the file is a relative file. | |
C9C9 | D0 03 | BNE $C9CE | If not a relative file (Z flag not set on return). branch to CY10A. | |
C9CB | 20 53 CA | JSR $CA53 | JSR to CYEXT ($CA53) to open copy the relative file records. | |
CY10A | C9CE | A9 08 | LDA #$08 | Store $08 (EOI signal) into EOIFLG($F8). |
C9D0 | 85 F8 | STA $F8 | ||
C9D2 | 4C D8 C9 | JMP $C9D8 | JMP to CY20. | |
CY15 | C9D5 | 20 9B CF | JSR $CF9B | JSR to PIBYTE ($CF9B) to write out last byte to disk. |
CY20 | C9D8 | 20 35 CA | JSR $CA35 | JSR to GIBYTE ($CA35) to get a byte from the internal read channel. |
C9DB | A9 80 | LDA #$80 | Load .A with $80 (the last record flag) and JSR to TSTFLG ($DDA6) to see if this is the last record. | |
C9DD | 20 A6 DD | JSR $DDA6 | ||
C9E0 | F0 F3 | BEQ $C9D5 | On return if Z flag is set (test failed; this is not the last record) branch to CY15 to do some more. Last record done so JSR to TYPFIL ($D125) to get file type. | |
C9E2 | 20 25 D1 | JSR $D125 | ||
C9E5 | F0 03 | BEQ $C9EA | On return if Z flag is set branch to CY30 to do some more. | |
C9E7 | 20 9B CF | JSR $CF9B | JSR to PIBYTE ($CF9B) to write out last byte to disk. | |
CY30 | C9EA | AE 79 02 | LDX $0279 | Check if there are more files to copy by loading .X from F2PTR ($0279) , incrementing it by 1, and comparing it to F2CNT ($0278). If the carry bit is clear, there are more files to copy so branch back to CY10. |
C9ED | E8 | INX | ||
C9EE | EC 78 02 | CPX $0278 | ||
C9F1 | 90 C6 | BCC $C9B9 | ||
C9F3 | A9 12 | LDA #$12 | Since no more files to copy, set the SA ($83) to $12 (internal write channel) and JMP to CLSCHN ($DB02) to close the copy channel and file. | |
C9F5 | 85 83 | STA $83 | ||
C9F7 | 4C 02 DB | JMP $DB02 | ||
Open internal read channel to read file |
||||
OPIRFL | C9FA | AE 79 02 | LDX $0279 | Load .X with the file pointer F2PTR ($0279) and use this as an index to load .A with the drive number of the file to be read from FILDRV,X ($E2,X). AND this drive number with $01 to mask off the default drive bit, and store the value in DRVNUM ($7F) to set the drive number. |
C9FD | B5 E2 | LDA $E2,X | ||
C9FF | 29 01 | AND #$01 | ||
CA01 | 85 7F | STA $7F | ||
CA03 | AD 85 FE | LDA $FE85 | Set the current TRACK ($80) to 18 ($12), the directory track. | |
CA06 | 85 80 | STA $80 | ||
CA08 | B5 D8 | LDA $D8,X | Set the current SECTOR ($81) to the sector containing the directory entry for this file from ENTSEC,X ($D8,X). the directory track. | |
CA0A | 85 81 | STA $81 | ||
CA0C | 20 75 D4 | JSR $D475 | JSR to OPNIRD ($D475) to open the internal read channel to read the directory. | |
CA0F | AE 79 02 | LDX $0279 | Load .X with the file pointer F2PTR ($0279) and use this as an index to load .A with the pointer to the start of the entry from ENTIND,X ($DD,X). | |
CA12 | B5 DD | LDA $DD,X | ||
CA14 | 20 C8 D4 | JSR $D4C8 | JSR to SETPNT ($D4C8) to set the track sector pointers from the entry. | |
CA17 | AE 79 02 | LDX $0279 | Load .X with the file pointer F2PTR ($0279) and use this as an index to load .A with the file's pattern mask from PATTYP,X ($E7,X). AND this value with $07 (the file type mask) and use it to set the file type in TYPE ($024A) . | |
CA1A | B5 E7 | LDA $E7,X | ||
CA1C | 29 07 | AND #$07 | ||
CA1E | 8D 4A 02 | STA $024A | ||
CA21 | A9 00 | LDA #$00 | Set the record length, REC ($0258) to $00 since this is not a relative file. | |
CA23 | 8D 58 02 | STA $0258 | ||
CA26 | 20 A0 D9 | JSR $D9A0 | JSR to OPREAD ($D9A0) to open a read channel . | |
CA29 | A0 01 | LDY #$01 | Load .Y with $01 and JSR to TYPFIL ($D125) to get the file type. | |
CA2B | 20 25 D1 | JSR $D125 | ||
CA2E | F0 01 | BEQ $CA31 | If Z flag set on return (indicates that this is not a relative file) branch to OPIR10. | |
CA30 | C8 | INY | Increment ,Y by 1. | |
OPIR10 | CA31 | 98 | TYA | Transfer the value in .Y into .A |
CA32 | 4C C8 D4 | JMP $D4C8 | Exit with a JMP to SETPNT ($D4C8) to set the track & sector pointers from the directory entry. | |
GIBYTE | CA35 | A9 11 | LDA #$11 | Get byte from internal read channel: Set the secondary address, SA ($83) to $11 (#17) the internal read channel. |
CA37 | 85 83 | STA $83 | ||
GCBYTE | CA39 | 20 9B D3 | JSR $D39B | Get byte from any channel: JSR to GBYTE ($D39B) to get the next byte from the read channel. |
CA3C | 85 85 | STA $85 | Store the byte in DATA ($85) . | |
CA3E | A6 82 | LDX $82 | Load .X with the logical file index LINDX ($82) and use this as an index to load .A with the channel status flag, CHNRDY,X | |
CA40 | B5 F2 | LDA $F2,X | ||
CA42 | 29 08 | AND #$08 | EOR .A with $08, the not EOI send code and store the result in EOIFLG ($F8) . | |
CA44 | 85 F8 | STA $F8 | ||
CA46 | D0 0A | BNE $CA52 | If .A <> $00 (EOI was sent!), branch to GIB20 and exit. | |
CA48 | 20 25 D1 | JSR $D125 | JSR to TYPFIL (SD125) to get the file type. If Z flag set on return (indicates this is not a relative file). branch to GIB20 and exit. | |
CA4B | F0 05 | BEQ $CA52 | ||
CA4D | A9 80 | LDA #$80 | Load .A with $80 (the last record flag) and JSR to SETFLG ($DD97) . | |
CA4F | 20 97 DD | JSR $DD97 | ||
GIB20 | CA52 | 60 | RTS | Terminate routine with an RTS. |
Copy relative records |
||||
CYEXT | CA53 | 20 D3 D1 | JSR $D1D3 | JSR to SETDRN ($D1D3) to set drive #. |
CA56 | 20 CB E1 | JSR $E1CB | JSR to SSEND ($E1CB) to position side sector and BUFTAB to the end of the last record. | |
CA59 | A5 D6 | LDA $D6 | Save side sector index, SSIND ($D6) and the side sector number, SSNUM ($D5) onto the stack. | |
CA5B | 48 | PHA | ||
CA5C | A5 D5 | LDA $D5 | ||
CA5E | 48 | PHA | ||
CA5F | A9 12 | LDA #$12 | Set the secondary address, SA ($83) to $12, the internal write channel . | |
CA61 | 85 83 | STA $83 | ||
CA63 | 20 07 D1 | JSR $D107 | JSR to FNDWCH ($D107) to find an unused write channel. | |
CA66 | 20 D3 D1 | JSR $D1D3 | JSR to SETDRN ($D1D3) to set drive #. | |
CA69 | 20 CB E1 | JSR $E1CB | JSR to SSEND ($E1CB) to position side sector and BUFTAB to th eend of the last record. | |
CA6C | 20 9C E2 | JSR $E29C | JSR to POSBUF ($E2C9) to position the proper data blocks into the buffers. | |
CA6F | A5 D6 | LDA $D6 | Set Rl ($87) to the current value of the side sector index, SSIND ($D6) . | |
CA71 | 85 87 | STA $87 | ||
CA73 | A5 D5 | LDA $D5 | Set RO ($86) to the current value of the side sector number, SSNUM ($D5) . | |
CA75 | 85 86 | STA $86 | ||
CA77 | A9 00 | LDA #$00 | Zero R2 ($88) and the low bytes of the record pointer RECPTR ($D4) and the relative file pointer ($D7) . | |
CA79 | 85 88 | STA $88 | ||
CA7B | 85 D4 | STA $D4 | ||
CA7D | 85 D7 | STA $D7 | ||
CA7F | 68 | PLA | Restore the original values of the side side sector number, SSNUM ($D5) and the sector index, SSIND ($D6) from the stack | |
CA80 | 85 D5 | STA $D5 | ||
CA82 | 68 | PLA | ||
CA83 | 85 D6 | STA $D6 | ||
CA85 | 4C 3B E3 | JMP $E33B | Terminate the routine with a JMP to ADDR1 ($E33B). | |
Rename file in the directory |
||||
RENAME | CA88 | 20 20 C3 | JSR $C320 | JSR to ALLDRS ($C320) to set up all the drives given in the command string. |
CA8B | A5 E3 | LDA $E3 | Load .A with the drive specified for the second file from FILDRV+1 ($E3). AND it with $01 to mask off the default drive bit, and store the result back in FILDRV+1 ($E3). | |
CA8D | 29 01 | AND #$01 | ||
CA8F | 85 E3 | STA $E3 | ||
CA91 | C5 E2 | CMP $E2 | Compare the second drive number (in .A) with the first one in FILDRV ($E2). If equal, branch to RN10. | |
CA93 | F0 02 | BEQ $CA97 | ||
CA95 | 09 80 | ORA #$80 | OR the drive number in .A with $80 to set bit 7. This will force a search of both drives for the named file. | |
RN10 | CA97 | 85 E2 | STA $E2 | Store the value in .A into FILDRV ($E2) |
CA99 | 20 4F C4 | JSR $C44F | JSR to LOOKUP ($C44F) to look up both file names in the directory. | |
CA9C | 20 E7 CA | JSR $CAE7 | JSR to CHKIO ($CAE7) to check for the existance of the files named. | |
CA9F | A5 E3 | LDA $E3 | Load the value from FILDRV+1 ($E3), AND it with $01 to mask off the default drive bit, and use the result to set the currently active drive, DRVNUM ($7F) . | |
CAA1 | 29 01 | AND #$01 | ||
CAA3 | 85 7F | STA $7F | ||
CAA5 | A5 D9 | LDA $D9 | Set the active sector number, SECTOR ($81) using the directory sector in which the second file name was found (from ENTSEC+1; $D9). | |
CAA7 | 85 81 | STA $81 | ||
CAA9 | 20 57 DE | JSR $DE57 | JSR to RDAB ($DE57) to read the directory sector specified in TRACK ($80) and SECTOR ($81) . | |
CAAC | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the job to be completed. | |
CAAF | A5 DE | LDA $DE | Load .A with the pointer to the entry in the buffer from ENTIND+1 ($DE). add $03 (so it points to the first character in the file name), and JSR to SETPNT ($D4C8) to set the pointers to the file name. | |
CAB1 | 18 | CLC | ||
CAB2 | 69 03 | ADC #$03 | ||
CAB4 | 20 C8 D4 | JSR $D4C8 | ||
CAB7 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to store the active buffer number in .A. | |
CABA | A8 | TAY | Transfer the buffer number to .Y. load .X from the file table FILTBL ($027A), .A with $10 (the number of characters in a file name) and JSR to TRNAME ($C66E) to transfer the file name from the command string to the buffer containing the file entry. | |
CABB | AE 7A 02 | LDX $027A | ||
CABE | A9 10 | LDA #$10 | ||
CAC0 | 20 6E C6 | JSR $C66E | ||
CAC3 | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write out the revised directory sector. | |
CAC6 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the job to be completed. | |
CAC9 | 4C 94 C1 | JMP $C194 | Terminate the routine with a JMP to ENDCMD ($C194) . | |
CHKIN | CACC | A5 E8 | LDA $E8 | Check existance of input file: Load .A with the first file type from PATTYP+1 ($E8). AND it with the file type mask ($07) and store it in TYPE ($024A) . |
CACE | 29 07 | AND #$07 | ||
CAD0 | 8D 4A 02 | STA $024A | ||
CAD3 | AE 78 02 | LDX $0278 | Load .X from F2CNT ($0278). | |
CK10 | CAD6 | CA | DEX | Decrement .X by 1 and compare it with the value of F1CNT ($0277). |
CAD7 | EC 77 02 | CPX $0277 | ||
CADA | 90 0A | BCC $CAE6 | If the carry is clear, the file has been found so branch to CK10. | |
CADC | BD 80 02 | LDA $0280,X | Load .A with the file's track link from FILTRK f X ($0280, X). If link is NOT $00, branch to CK10. | |
CADF | D0 F5 | BNE $CAD6 | ||
CAE1 | A9 62 | LDA #$62 | Since the file has not been found, load .A with $62 and exit with a JMP to CMDERR ($C1C8) . | |
CAE3 | 4C C8 C1 | JMP $C1C8 | ||
CK20 | CAE6 | 60 | RTS | Terminate routine with an RTS. |
Check existance of I/O file |
||||
CHKIO | CAE7 | 20 CC CA | JSR $CACC | JSR to CHKIN ($CACC) to check for the existance of the input file. |
CK25 | CAEA | BD 80 02 | LDA $0280,X | Load .A with the file's track link from FILTRK,X ($0280, X). If link equals $00, branch to CK30. |
CAED | F0 05 | BEQ $CAF4 | ||
CAEF | A9 63 | LDA #$63 | The file already exists so load .A with $62 and exit with a JMP to CMDERR ($C1C8) | |
CAF1 | 4C C8 C1 | JMP $C1C8 | ||
CK30 | CAF4 | CA | DEX | Decrement .X (file counter). If more files exist, branch back to CK25. CMDERR ($C1C8) . |
CAF5 | 10 F3 | BPL $CAEA | ||
CAF7 | 60 | RTS | Terminate routine with an RTS. | |
Memory access commands (M-R, M-W, AND M-E) |
||||
MEM | CAF8 | AD 01 02 | LDA $0201 | Check that the second character in the command is a "-" by: loading .A with the character from CMDBUF + 1 ($0201) , and comparing it with $2D ("-"). If not equal, branch to MEMERR ($CB4B). |
CAFB | C9 2D | CMP #$2D | ||
CAFD | D0 4C | BNE $CB4B | ||
CAFF | AD 03 02 | LDA $0203 | Set up address specified in command by moving the characters from CMDBUF+3 ($0202) and CMDBUF+4 ($0203) to TEMP ($6F) and TEMP+1 ($70) . | |
CB02 | 85 6F | STA $6F | ||
CB04 | AD 04 02 | LDA $0204 | ||
CB07 | 85 70 | STA $70 | ||
CB09 | A0 00 | LDY #$00 | Set .Y to $00. | |
CB0B | AD 02 02 | LDA $0202 | Load .A with the third character of the command (R,W,E) from CMDBUF+2 ($0202) . | |
CB0E | C9 52 | CMP #$52 | Compare .A with "R". If equal, branch to MEMRD ($CB20) . | |
CB10 | F0 0E | BEQ $CB20 | ||
CB12 | 20 58 F2 | JSR $F258 | JSR to KILLP ($F258) to kill protection, NOTE: this does nothing on the 1541! | |
CB15 | C9 57 | CMP #$57 | Compare .A with "W". If equal, branch to MEMWRT ($CB50) . | |
CB17 | F0 37 | BEQ $CB50 | ||
CB19 | C9 45 | CMP #$45 | Compare .A with "E". If NOT equal, branch to MEMERR ($CB4B). | |
CB1B | D0 2E | BNE $CB4B | ||
MEMEX | CB1D | 6C 6F 00 | JMP ($006F) | Do indirect jump using the pointer set up in TEMP ($006F) . |
MEMRD | CB20 | B1 6F | LDA ($6F),Y | Load .A with the contents of (TEMP) ,Y ($6F) ,Y and store the value in DATA($85) |
CB22 | 85 85 | STA $85 | ||
CB24 | AD 74 02 | LDA $0274 | Compare the command string length, CMDSIZ ($0274), with $06. If it is less than or equal to 6 (normally 5). branch to M30. | |
CB27 | C9 06 | CMP #$06 | ||
CB29 | 90 1A | BCC $CB45 | ||
Multi-byte memory read:
|
||||
MRMULT | CB2B | AE 05 02 | LDX $0205 | Load .X with the 6th character in the command string from CMDBUF+5 ($0205). |
CB2E | CA | DEX | Decrement .X (now $00 if only one to read) . | |
CB2F | F0 14 | BEQ $CB45 | If the result is $00, all done so branch to M30. | |
CB31 | 8A | TXA | Transfer the value in .X to .A and clear the carry flag. | |
CB32 | 18 | CLC | ||
CB33 | 65 6F | ADC $6F | Add the lo byte of the memory pointer in TEMP ($6F). This value is the lo byte of the last character to be sent. | |
CB35 | E6 6F | INC $6F | Increment the lo byte pointer in TEMP ($6F) so it points to the second memory location to be read. | |
CB37 | 8D 49 02 | STA $0249 | Store the value in .A into LSTCHR+ERRCHN ($0249) . | |
CB3A | A5 6F | LDA $6F | Load .A with the current value of TEMP ($6A). the lo byte of the second memory location to be read and store this value in CB+2 ($A5) . | |
CB3C | 85 A5 | STA $A5 | ||
CB3E | A5 70 | LDA $70 | Load .A with the current value of TEMP+1 ($70). the hi byte of the second memory location to be read and store this value in CB+3 ($A6) . | |
CB40 | 85 A6 | STA $A6 | ||
CB42 | 4C 43 D4 | JMP $D443 | Continue memory read with a JMP to GE20 ($D443) . | |
M30 | CB45 | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. |
CB48 | 4C 3A D4 | JMP $D43A | Terminate memory read with a JMP to GE15 ($D43A). | |
MEMERR | CB4B | A9 31 | LDA #$31 | Load .A with $31 to indicate a bad command and JMP to CMDERR ($C1C8). |
CB4D | 4C C8 C1 | JMP $C1C8 | ||
MEMWRT | CB50 | B9 06 02 | LDA $0206,Y | Move byte from CMDBUF+6,Y ($0206, Y) to memory at TEMP,Y ($BF,Y). |
CB53 | 91 6F | STA ($6F),Y | ||
CB55 | C8 | INY | Increment .Y and compare .Y with the number of bytes to do, CMDBUF+5 ($0205). | |
CB56 | CC 05 02 | CPY $0205 | ||
CB59 | 90 F5 | BCC $CB50 | If more to do, branch back to M10. | |
CB5B | 60 | RTS | Terminate memory write with an RTS. | |
User commands
|
||||
User jump commands |
||||
USER | CB5C | AC 01 02 | LDY $0201 | Load .Y with the second byte of the command string from CMDBUF+1 ($0201) . |
CB5F | C0 30 | CPY #$30 | Compare .Y to $30. If not equal, this is NOT a U0 command so branch to US10. | |
CB61 | D0 09 | BNE $CB6C | ||
USRINT | CB63 | A9 EA | LDA #$EA | Restore normal user jump address ($FFEA) storing $EA in USRJMP ($6B) and $FF in USRJMP+1 ($6C) . |
CB65 | 85 6B | STA $6B | ||
CB67 | A9 FF | LDA #$FF | ||
CB69 | 85 6C | STA $6C | ||
CB6B | 60 | RTS | Terminate routine with an RTS. | |
US10 | CB6C | 20 72 CB | JSR $CB72 | JSR to USREXC ($CB72) to execute the code according to the jump table. |
CB6F | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) . | |
USREXC | CB72 | 88 | DEY | Decrement .Y, transfer the value to .A, AND it with $0F to convert it to hex, multiply it by two (ASL). and transfer the result back into .Y. |
CB73 | 98 | TYA | ||
CB74 | 29 0F | AND #$0F | ||
CB76 | 0A | ASL | ||
CB77 | A8 | TAY | ||
CB78 | B1 6B | LDA ($6B),Y | Transfer the lo byte of the user jump address from the table at (USRJMP) ,Y to IP ($75) . | |
CB7A | 85 75 | STA $75 | ||
CB7C | C8 | INY | Increment .Y by 1. | |
CB7D | B1 6B | LDA ($6B),Y | Transfer the hi byte of the user jump address from the table at (USRJMP) ,Y to IP + 1 ($76) . | |
CB7F | 85 76 | STA $76 | ||
CB81 | 6C 75 00 | JMP ($0075) | Do an indirect jump to the user code through the vector at IP ($0076) . | |
Open direct access buffer in response to an OPEN "#" command |
||||
OPNBLK | CB84 | AD 8E 02 | LDA $028E | Use the previous drive number, LSTDRV ($028E) to set the current drive number DRVNUM ($7F) . |
CB87 | 85 7F | STA $7F | ||
CB89 | A5 83 | LDA $83 | Save the current secondary address, SA ($83) on the stack. | |
CB8B | 48 | PHA | ||
CB8C | 20 3D C6 | JSR $C63D | JSR to AUTOI ($C63D) to initialize the disk. This is necessary for proper channel assignment. | |
CB8F | 68 | PLA | Restore the original secondary address , SA ($83) by pulling it off the stack. | |
CB90 | 85 83 | STA $83 | ||
CB92 | AE 74 02 | LDX $0274 | Load .X with the command string length CMDSIZ ($0274). Decrement .X by 1. | |
CB95 | CA | DEX | ||
CB96 | D0 0D | BNE $CBA5 | If .X not egual to zero, a specific buffer number has been requested (e .g. #1) so branch to OB10. | |
CB98 | A9 01 | LDA #$01 | No specific buffer requested so get any available buffer by loading .A with $01 and doing a JSR to GETRCH ($D1E2). | |
CB9A | 20 E2 D1 | JSR $D1E2 | ||
CB9D | 4C F1 CB | JMP $CBF1 | On return, JMP to OB30. | |
OB05 | CBA0 | A9 70 | LDA #$70 | Load .A with $70 to indicate that no channel is available and JMP to CMDERR ($C1C8) . |
CBA2 | 4C C8 C1 | JMP $C1C8 | ||
OB10 | CBA5 | A0 01 | LDY #$01 | Specific buffer requested so load .Y with $01 and JSR to BP05 ($CC7C) to check the block parameters. |
CBA7 | 20 7C CC | JSR $CC7C | ||
CBAA | AE 85 02 | LDX $0285 | Load .X with the number of the buffer requested from FILSEC ($0285) and check it against $05 (the highest numbered buffer available). If too large, branch to OB05 and abort the command. | |
CBAD | E0 05 | CPX #$05 | ||
CBAF | B0 EF | BCS $CBA0 | ||
CBB1 | A9 00 | LDA #$00 | Set TEMP ($6F) and TEMP+1 ($70) to $00 and set the carry flag. | |
CBB3 | 85 6F | STA $6F | ||
CBB5 | 85 70 | STA $70 | ||
CBB7 | 38 | SEC | ||
OB15 | CBB8 | 26 6F | ROL $6F | Loop to shift a 1 into the bit position in TEMP or TEMP+1 that corresponds to the buffer requested. For example:
|
CBBA | 26 70 | ROL $70 | ||
CBBC | CA | DEX | ||
CBBD | 10 F9 | BPL $CBB8 | ||
CBBF | A5 6F | LDA $6F | Load .A with the value in TEMP ($6F) and AND it with the value in BUFUSE ($024F) which indicates which buffers are already in use. If the result is NOT $00, the buffer requested is already in use so branch to OB05 to abort. | |
CBC1 | 2D 4F 02 | AND $024F | ||
CBC4 | D0 DA | BNE $CBA0 | ||
CBC6 | A5 70 | LDA $70 | Load .A with the value in TEMP+1 ($70) and AND it with the value in BUFUSE+1 ($0250) which indicates which buffers are already in use. If the result is NOT $00, the buffer requested is already in use so branch to OB05 to abort. | |
CBC8 | 2D 50 02 | AND $0250 | ||
CBCB | D0 D3 | BNE $CBA0 | ||
CBCD | A5 6F | LDA $6F | Mark the buffer requested as in use by ORing the value in TEMP with the value in BUFUSE and the value in TEMP+1 with the value in BUFUSE+1. | |
CBCF | 0D 4F 02 | ORA $024F | ||
CBD2 | 8D 4F 02 | STA $024F | ||
CBD5 | A5 70 | LDA $70 | ||
CBD7 | 0D 50 02 | ORA $0250 | ||
CBDA | 8D 50 02 | STA $0250 | ||
CBDD | A9 00 | LDA #$00 | Set up the channel by loading .A with $00 and doing a JSR to GETRCH ($D1E2) to find an unused read channel. | |
CBDF | 20 E2 D1 | JSR $D1E2 | ||
CBE2 | A6 82 | LDX $82 | Load .X with the current channel* from LINDX ($82) . | |
CBE4 | AD 85 02 | LDA $0285 | Use .X as an index to move the sector link from FILSEC ($0285) to BUFO. X ($A7 , X) | |
CBE7 | 95 A7 | STA $A7,X | ||
CBE9 | AA | TAX | Transfer the sector link from .A to .X. | |
CBEA | A5 7F | LDA $7F | Use .X as an index to move the current drive number from DRVNUM($7F) to JOBS,X ($00, X) and to LSTJOB,X ($025B,X) . | |
CBEC | 95 00 | STA $00,X | ||
CBEE | 9D 5B 02 | STA $025B,X | ||
OB30 | CBF1 | A6 83 | LDX $83 | Load .X with the current secondary address, SA ($83) • |
CBF3 | BD 2B 02 | LDA $022B,X | Load .A with the current value from the logical index table, LINTAB,X ($022B,X) . OR this value with $40 to indicate that it is read/write mode and store the result back in LINTAB,X. | |
CBF6 | 09 40 | ORA #$40 | ||
CBF8 | 9D 2B 02 | STA $022B,X | ||
CBFB | A4 82 | LDY $82 | Load .Y with the current channel#, LINDX ($82) . | |
CBFD | A9 FF | LDA #$FF | Load .A with $FF and store this value as the channel's last character pointer LSTCHR,Y ($0244, Y) . | |
CBFF | 99 44 02 | STA $0244,Y | ||
CC02 | A9 89 | LDA #$89 | Load .A with $89 and store this value in CHNRDY,Y ($00F2,Y) to indicate that the channel is a random access one and is ready. | |
CC04 | 99 F2 00 | STA $00F2,Y | ||
CC07 | B9 A7 00 | LDA $00A7,Y | Load .A with the channel number from BUF0,Y ($00A7,Y) and store it in CHNDAT,Y($023E,Y) as the first character | |
CC0A | 99 3E 02 | STA $023E,Y | ||
CC0D | 0A | ASL | Multiply the sector value in .A by 2 and transfer the result into .X | |
CC0E | AA | TAX | ||
CC0F | A9 01 | LDA #$01 | Set the buffer table value BUFTAB,X ($99, X) to $01. | |
CC11 | 95 99 | STA $99,X | ||
CC13 | A9 0E | LDA #$0E | Set the file type value FILTYP,Y ($EC,Y) to $0E to indicate a direct access file type. | |
CC15 | 99 EC 00 | STA $00EC,Y | ||
CC18 | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C1C4) . | |
Block commands (B-A; B-F; B-R; B-W; B-E; B-P) |
||||
BLOCK | CC1B | A0 00 | LDY #$00 | Zero .X and .Y. Load .A with $2D ("-") and JSR to PARSE ($C268) to locate the sub-command (separated from the command with a "-") . |
CC1D | A2 00 | LDX #$00 | ||
CC1F | A9 2D | LDA #$2D | ||
CC21 | 20 68 C2 | JSR $C268 | ||
CC24 | D0 0A | BNE $CC30 | On return branch to BLK40 if Z flag is not set ("-" was found). | |
BLK10 | CC26 | A9 31 | LDA #$31 | Load .A with $31 to indicate a bad command and JMP to CMDERR ($C1C8). |
CC28 | 4C C8 C1 | JMP $C1C8 | ||
BLK30 | CC2B | A9 30 | LDA #$30 | Load .A with $30 to indicate a bad syntax and JMP to CMDERR ($C1C8) . |
CC2D | 4C C8 C1 | JMP $C1C8 | ||
BLK40 | CC30 | 8A | TXA | Transfer the value in .X to .A. If not $00, branch to BLK30. |
CC31 | D0 F8 | BNE $CC2B | ||
CC33 | A2 05 | LDX #$05 | Load .X with $05 (the number of block commands - 1) . | |
CC35 | B9 00 02 | LDA $0200,Y | Load .A with the first character in the sub-command from CMDBUF,Y ($0200, Y). | |
BLK50 | CC38 | DD 5D CC | CMP $CC5D,X | Loop to compare the first character in the sub-command with the characters in the command table BCTAB,X ($CC5D,X). If a match is found. branch to BLK60. If NO MATCH is found, branch to BLK10. |
CC3B | F0 05 | BEQ $CC42 | ||
CC3D | CA | DEX | ||
CC3E | 10 F8 | BPL $CC38 | ||
CC40 | 30 E4 | BMI $CC26 | ||
BLK60 | CC42 | 8A | TXA | Transfer the pointer to the command in the command table from .X to .A. OR this value with $80 and store it as the command number in CMDNUM ($022A) . |
CC43 | 09 80 | ORA #$80 | ||
CC45 | 8D 2A 02 | STA $022A | ||
CC48 | 20 6F CC | JSR $CC6F | JSR to BLKPAR ($CC6F) to parse the block parameters. | |
CC4B | AD 2A 02 | LDA $022A | Load .A with the command number from CMDNUM ($022A), multiply it by 2 (ASL) , and transfer the result into .X. | |
CC4E | 0A | ASL | ||
CC4F | AA | TAX | ||
CC50 | BD 64 CC | LDA $CC64,X | Use .X as an index into the jump table BCJMP,X ($CC63) to set up a jump vector to the ROM routine at TEMP ($6F/70) . | |
CC53 | 85 70 | STA $70 | ||
CC55 | BD 63 CC | LDA $CC63,X | ||
CC58 | 85 6F | STA $6F | ||
CC5A | 6C 6F 00 | JMP ($006F) | Do an indirect JMP to the appropriate ROM routine via the vector at TEMP($6F). | |
CC5D | 41 46 52 57 45 50 | Block sub-command table ($CC5D-$CC62) .BYTE "AFRWEP" | ||
CC63 | 03 CD F5 CC 56 CD 73 CD A3 CD BD CD | Block jump table ($CC63-$CC6E)
| ||
Parse the block parameters |
||||
BLKPAR | CC6F | A0 00 | LDY #$00 | Zero .X and .Y. Load .A with $3A ( " : " ) and JSR to PARSE ($C268) to find the colon, if any. |
CC71 | A2 00 | LDX #$00 | ||
CC73 | A9 3A | LDA #$3A | ||
CC75 | 20 68 C2 | JSR $C268 | ||
CC78 | D0 02 | BNE $CC7C | On return branch to BP05 if Z flag is not set (":" found; .Y=":"-position+1) | |
CC7A | A0 03 | LDY #$03 | Load .Y with $03 (start of parameters) | |
BP05 | CC7C | B9 00 02 | LDA $0200,Y | Load .A with the .Yth character from the command string. |
CC7F | C9 20 | CMP #$20 | Compare the character in .A with $20, (a space). If equal, branch to BP10. | |
CC81 | F0 08 | BEQ $CC8B | ||
CC83 | C9 1D | CMP #$1D | Compare the character in .A with $29, (a skip chr). If equal, branch to BP10. | |
CC85 | F0 04 | BEQ $CC8B | ||
CC87 | C9 2C | CMP #$2C | Compare the character in .A with $2C, (a comma). If NOT equal, branch to BP20« | |
CC89 | D0 07 | BNE $CC92 | ||
BP10 | CC8B | C8 | INY | Increment .Y. Compare .Y to the length of the command string in CMDSIZ ($0274) , If more left, branch back to BP05. |
CC8C | CC 74 02 | CPY $0274 | ||
CC8F | 90 EB | BCC $CC7C | ||
CC91 | 60 | RTS | If no more, exit with an RTS. | |
BP20 | CC92 | 20 A1 CC | JSR $CCA1 | JSR to ASCHEX ($CCA1) to convert ASCII values into hex and store the results in tables. |
CC95 | EE 77 02 | INC $0277 | Increment the number of parameters processed F1CNT ($0277) . | |
CC98 | AC 79 02 | LDY $0279 | Load .Y with the value in F2PTR ($0279) | |
CC9B | E0 04 | CPX #$04 | Compare the value in .X (the original value of F1CNT ($0277) to $04 (the maximun number of files - 1). If the value in .X <= $04, branch to BP10. | |
CC9D | 90 EC | BCC $CC8B | ||
CC9F | B0 8A | BCS $CC2B | If .X was > $04. the syntax is bad so branch to BLK30 ($CC2B) . | |
Convert ASCII to HEXIt stores the converted values in the FILTRK ($0280) and FILSEC ($0285) tables On entry: .Y = pointer into CMD buffer |
||||
ASCHEX | CCA1 | A9 00 | LDA #$00 | Zero TEMP($6F) r TEMP+1 ($70), and TEMP+3 ($72) as a work area. |
CCA3 | 85 6F | STA $6F | ||
CCA5 | 85 70 | STA $70 | ||
CCA7 | 85 72 | STA $72 | ||
CCA9 | A2 FF | LDX #$FF | Load .X with $FF. | |
AH10 | CCAB | B9 00 02 | LDA $0200,Y | Load .A with the command string byte from CMDBUF,Y. |
CCAE | C9 40 | CMP #$40 | Test if the character in .A is numeric by comparing it to $40. If non-numeric, branch to AH20. | |
CCB0 | B0 18 | BCS $CCCA | ||
CCB2 | C9 30 | CMP #$30 | Test if the character in .A is ASCII by comparing it to $30. If it is not an ASCII digit, branch to AH20. | |
CCB4 | 90 14 | BCC $CCCA | ||
CCB6 | 29 0F | AND #$0F | AND the ASCII digit with $0F to mask off the higher order bits and save this new value on the stack. | |
CCB8 | 48 | PHA | ||
CCB9 | A5 70 | LDA $70 | Shift the values already in the table one position (TEMP+1 goes into TEMP+2; TEMP goes into TEMP+1) . | |
CCBB | 85 71 | STA $71 | ||
CCBD | A5 6F | LDA $6F | ||
CCBF | 85 70 | STA $70 | ||
CCC1 | 68 | PLA | Pull the new value off the stack and store it in TEMP. | |
CCC2 | 85 6F | STA $6F | ||
CCC4 | C8 | INY | Increment .Y and compare it to the command length stored in CMDSIZ ($0274) . If more command left, branch back to AH10. Convert the values in the TEMP table into a single hex byte: | |
CCC5 | CC 74 02 | CPY $0274 | ||
CCC8 | 90 E1 | BCC $CCAB | ||
AH20 | CCCA | 8C 79 02 | STY $0279 | Save the .Y pointer to the command string into F2PTR ($0279). clear the the carry flag, and load .A with $00. |
CCCD | 18 | CLC | ||
CCCE | A9 00 | LDA #$00 | ||
AH30 | CCD0 | E8 | INX | Increment .X by 1 (index into TEMP) . |
CCD1 | E0 03 | CPX #$03 | Compare .X to $03 to see if we're done yet. If done, branch to AH40. | |
CCD3 | B0 0F | BCS $CCE4 | ||
CCD5 | B4 6F | LDY $6F,X | Load .Y from TEMP,Y ($6F,Y). | |
AH35 | CCD7 | 88 | DEY | Decrement .Y by 1. If Y<0 branch to AH30 |
CCD8 | 30 F6 | BMI $CCD0 | ||
CCDA | 7D F2 CC | ADC $CCF2,X | Add (with carry) the value from DECTAB,X ($CCF2,X) to .A. This adds 1, 10 or 100. If there is no carry, branch to AH35. | |
CCDD | 90 F8 | BCC $CCD7 | ||
CCDF | 18 | CLC | Since there is a carry, clear the carry, increment TEMP+3, and branch back to AH35 . | |
CCE0 | E6 72 | INC $72 | ||
CCE2 | D0 F3 | BNE $CCD7 | ||
AH40 | CCE4 | 48 | PHA | Save the contents of .A (the hex number) onto the stack. |
CCE5 | AE 77 02 | LDX $0277 | Load .X with the command segment counter from F1CNT ($0277) . | |
CCE8 | A5 72 | LDA $72 | Load .A with the carry bit (thousands) from TEMP+3 ($72) and store it in the table, FILTRK,X ($0280, X). | |
CCEA | 9D 80 02 | STA $0280,X | ||
CCED | 68 | PLA | Pull the hex number off the stack and store it in the table, FILSEC,X ($0285 ,X) | |
CCEE | 9D 85 02 | STA $0285,X | ||
CCF1 | 60 | RTS | Terminate routine with an RTS. | |
DECTAB | CCF2 | 01 0A 64 | The decimal conversion table: Byte $01 = 1 Byte $0A = 10 Byte $64 = 100 | |
Free (de-allocate) block in the BAM |
||||
BLKFRE | CCF5 | 20 F5 CD | JSR $CDF5 | JSR to BLKTST ($CDF5) to test for legal block and set up track & sector. |
CCF8 | 20 5F EF | JSR $EF5F | JSR to FRETS ($EF5F) to free the block in the BAM and mark the BAM as changed. | |
CCFB | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD (SC194) . | |
CCFE | A9 01 | LDA #$01 | Unused code: LDA #$01 / STA WBAM($02F9) | |
CD00 | 8D F9 02 | STA $02F9 | ||
BLKALC | CD03 | 20 F5 CD | JSR $CDF5 | Allocate a sector (block) in the BAM: JSR to BLKTST ($CDF5) to test for legal block and set up track & sector. |
CD06 | A5 81 | LDA $81 | Load .A with the current sector pointer SECTOR ($81) and save this on the stack | |
CD08 | 48 | PHA | ||
CD09 | 20 FA F1 | JSR $F1FA | JSR to GETSEC ($F1FA) to set the BAM and find the next available sector on this track. | |
CD0C | F0 0B | BEQ $CD19 | If Z flag is set on return to indicate that the desired sector is in use and there is no greater sector available on this track, branch to BA15. | |
CD0E | 68 | PLA | Pull the requested sector from the stack and compare it to the current contents of SECTOR ($81). if not equal, the requested sector is already in use so branch to BA30. | |
CD0F | C5 81 | CMP $81 | ||
CD11 | D0 19 | BNE $CD2C | ||
CD13 | 20 90 EF | JSR $EF90 | Requested sector is available so JSR to WUSED ($EF90, to allocate the sector in the TM A ^ and terminate the command with a JMP to ENDCMD ($C194). | |
CD16 | 4C 94 C1 | JMP $C194 | ||
BA15 | CD19 | 68 | PLA | Pull the desired sector'off the stack, it is of no further use since that sector is already in use. |
BA20 | CD1A | A9 00 | LDA #$00 | Set the desired sector, SECTOR ($81) to $00, increment the desired track, TRACK ($80) by 1, and check if we have reached the maximum track count of 3 5 (taken from MAXTRK $FECB). If we have gone all the way, branch to BA40. |
CD1C | 85 81 | STA $81 | ||
CD1E | E6 80 | INC $80 | ||
CD20 | A5 80 | LDA $80 | ||
CD22 | CD D7 FE | CMP $FED7 | ||
CD25 | B0 0A | BCS $CD31 | ||
CD27 | 20 FA F1 | JSR $F1FA | JSR to GETSEC ($F1FA) to set the BAM and find the next available sector on this track. | |
CD2A | F0 EE | BEQ $CD1A | If Z flag is set on return, no greater sector is available on this track so branch back to BA20 to try another track | |
BA30 | CD2C | A9 65 | LDA #$65 | Requested block is not available so load .A with $65 to indicate NO BLOCK ERROR and JMP to CMDER2 ($E645). |
CD2E | 20 45 E6 | JSR $E645 | ||
BA40 | CD31 | A9 65 | LDA #$65 | No free sectors are available so load .A with $65 to indicate NO BLOCK ERROR and JMP to CMDERR ($C1C8). |
CD33 | 20 C8 C1 | JSR $C1C8 | ||
B-R Sub to test parameters |
||||
BLKRD2 | CD36 | 20 F2 CD | JSR $CDF2 | JSR to BKOTST ($CDF2) to test block parameters and set track & sector. |
CD39 | 4C 60 D4 | JMP $D460 | JMP to DRTRD ($D460) to read block | |
GETSIM | CD3C | 20 2F D1 | JSR $D12F | B-R Sub to get byte w/o increment: JSR to GETPRE ($D12F) set parameters. |
CD3F | A1 99 | LDA ($99,X) | Load .A with the value in (BUFTAB,X) , ($99, X) . | |
CD41 | 60 | RTS | Terminate routine with an RTS. | |
B-R Sub to do read |
||||
BLKRD3 | CD42 | 20 36 CD | JSR $CD36 | JSR to BLKRD2 ($CD36) to test parameters |
CD45 | A9 00 | LDA #$00 | Zero .A and JSR to SETPNT ($D4C8) to set the track and sector pointers. | |
CD47 | 20 C8 D4 | JSR $D4C8 | ||
CD4A | 20 3C CD | JSR $CD3C | JSR to GETSIM ($CD3C) to read block. On return .Y is the LINDX. | |
CD4D | 99 44 02 | STA $0244,Y | Store the byte in .A into LSTCHR,Y ($0244, Y) as the last character. | |
CD50 | A9 89 | LDA #$89 | Store $89 in CHNRDT, Y ($F2. Y) to indicate that it is a random access channel and is now ready. | |
CD52 | 99 F2 00 | STA $00F2,Y | ||
CD55 | 60 | RTS | Exit routine with an RTS. | |
Block read a sector |
||||
BLKRD | CD56 | 20 42 CD | JSR $CD42 | JSR to BLKRD3 ($CD42) to set up to read the requested sector. |
CD59 | 20 EC D3 | JSR $D3EC | JSR to RNGET1 ($D3EC) to read in the sector. | |
CD5C | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) . | |
U1: Block read of a sector
|
||||
UBLKRD | CD5F | 20 6F CC | JSR $CC6F | JSR to BLKPAR ($CC6F) to parse the block parameters. |
CD62 | 20 42 CD | JSR $CD42 | JSR to BLKRD3 ($CD42) to set up to read the requested sector. | |
CD65 | B9 44 02 | LDA $0244,Y | Move the last character read from LSTCHR,Y ($0244, Y) to CHNDAT,Y ($023E f Y) | |
CD68 | 99 3E 02 | STA $023E,Y | ||
CD6B | A9 FF | LDA #$FF | Store $FF in LSTCHR,Y ($0244, Y) as the last character to be read. | |
CD6D | 99 44 02 | STA $0244,Y | ||
CD70 | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) which ends with an RTS. | |
Block-write of a sector |
||||
BLKWT | CD73 | 20 F2 CD | JSR $CDF2 | JSR to BKOTST ($CDF2) to test the buffer and block parameters and set up the drive, track, and sector pointers. |
CD76 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to read the active buffer pointers. On exit, .A points into the buffer. | |
CD79 | A8 | TAY | Transfer .A to .Y and decrement .Y. | |
CD7A | 88 | DEY | ||
CD7B | C9 02 | CMP #$02 | If the value in .A is greater than $02, branch to BW10 | |
CD7D | B0 02 | BCS $CD81 | ||
CD7F | A0 01 | LDY #$01 | Load .Y with $01. | |
BW10 | CD81 | A9 00 | LDA #$00 | Load .A with $00. |
CD83 | 20 C8 D4 | JSR $D4C8 | JSR to SETPNT ($D4C8) to set the buffer pointers. | |
CD86 | 98 | TYA | Transfer the value in .Y to .A and JSR to PUTBYT ($CFF1) to put the byte in .A into the active buffer of LINDX. | |
CD87 | 20 F1 CF | JSR $CFF1 | ||
CD8A | 8A | TXA | Transfer the value of .X to .A and save it on the stack. | |
CD8B | 48 | PHA | ||
BW20 | CD8C | 20 64 D4 | JSR $D464 | JSR to DRTWRT ($D464) to write out the block. |
CD8F | 68 | PLA | Pop the value off the stack and transfer it back into .X. | |
CD90 | AA | TAX | ||
CD91 | 20 EE D3 | JSR $D3EE | JSR to RNGET2 ($D3EE) to set the channel ready status and last character. | |
CD94 | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD /(SC194) which ends with an RTS. | |
U2: Block write of a sector |
||||
UBLKWT | CD97 | 20 6F CC | JSR $CC6F | JSR to BLKPAR ($CC6F) to parse the block parameters . |
CD9A | 20 F2 CD | JSR $CDF2 | JSR to BKOTST ($CDF2) to test the buffer and block parameters and set up the drive, track, and sector pointers. | |
CD9D | 20 64 D4 | JSR $D464 | JSR to DRTWRT ($D464) to write out the block. | |
CDA0 | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) which ends with an RTS. | |
Block execute a sector |
||||
BLKEXC | CDA3 | 20 58 F2 | JSR $F258 | JSR to KILLP ($F258) to kill the disk protection. Does nothing on the 1541! |
CDA6 | 20 36 CD | JSR $CD36 | JSR to BLKRD2 ($CC6F) to read the sector | |
CDA9 | A9 00 | LDA #$00 | Store $00 in TEMP ($6F) as the lo byte of the JMP address) | |
CDAB | 85 6F | STA $6F | ||
CDAD | A6 F9 | LDX $F9 | Load .X from JOBNUM ($F9) and use it as an index to load the hi byte of the JMP address from BUFIND,X ($FEE0,X) and store it in TEMP+1 ($70). | |
CDAF | BD E0 FE | LDA $FEE0,X | ||
CDB2 | 85 70 | STA $70 | ||
CDB4 | 20 BA CD | JSR $CDBA | JSR to BE10 ($CDBA) to execute the block. | |
CDB7 | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) which ends with an RTS. | |
BE10 | CDBA | 6C 6F 00 | JMP ($006F) | JMP (TEMP) Used by block execute, |
Set the buffer pointer |
||||
BLKPTR | CDBD | 20 D2 CD | JSR $CDD2 | JSR to BUFTST ($CDD2)to test for allocated buffer. |
CDC0 | A5 F9 | LDA $F9 | Load the buffer number of the channel requested from JUBNUM ($F9). multiply it by two (ASL). and transfer the result into .X. Load .A with the new buffer pointer value from FILSEC+1 ($0286) and store it in the buffer table BUFTAB,X ($99, X). | |
CDC2 | 0A | ASL | ||
CDC3 | AA | TAX | ||
CDC4 | AD 86 02 | LDA $0286 | ||
CDC7 | 95 99 | STA $99,X | ||
CDC9 | 20 2F D1 | JSR $D12F | JSR to GETPRE ($D12F) to set up pointers | |
CDCC | 20 EE D3 | JSR $D3EE | JSR to RNGET2 ($D3EE) to ready the channel for I/O | |
CDCF | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) which ends with an RTS. | |
BUFTST | CDD2 | A6 D3 | LDX $D3 | Test whether a buffer has been allocated for the secondary address given in SA. Load .X with the file stream 1 pointer, F1PTR ($D3) and then increment the original pointer F1PTR ($D3). |
CDD4 | E6 D3 | INC $D3 | ||
CDD6 | BD 85 02 | LDA $0285,X | Load .A with that file's secondary address from FILSEC,X ($0285, X). | |
CDD9 | A8 | TAY | Transfer the secondary address to .Y. Decrement it by 2 (to eliminate the reserved secondary addresses and 1) and compare the result with $0C (#12). If the original SA was between 2 and 14, it passes the test so branch to BT20. | |
CDDA | 88 | DEY | ||
CDDB | 88 | DEY | ||
CDDC | C0 0C | CPY #$0C | ||
CDDE | 90 05 | BCC $CDE5 | ||
BT15 | CDE0 | A9 70 | LDA #$70 | Load .A with $70 to indicate no channel is available and JMP to CMDERR ($C1C8). |
CDE2 | 4C C8 C1 | JMP $C1C8 | ||
BT20 | CDE5 | 85 83 | STA $83 | Store the original secondary address (in .A) into SA ($83) as the active SA. |
CDE7 | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB)to find an unused read channel. If none available, branch to BT15. | |
CDEA | B0 F4 | BCS $CDE0 | ||
CDEC | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number. On return, store the active buffer number in JOBNUM ($F9) . read channel. If none available, branch | |
CDEF | 85 F9 | STA $F9 | ||
CDF1 | 60 | RTS | Terminate routine with an RTS. | |
Test all block parameters: buffer allocated and legal block.If OK, set up drive, track, and sector values. |
||||
BKOTST | CDF2 | 20 D2 CD | JSR $CDD2 | JSR to BUFTST($CDD2) to test if buffer is allocated for this secondary address. |
BLKTST | CDF5 | A6 D3 | LDX $D3 | Set the drive number, track, and sector values requested for a block operation and test to see that these are valid. Load .X with the channel number from F1PTR ($D3) |
CDF7 | BD 85 02 | LDA $0285,X | Load .A with the drive number desired from FILSEC,X($0285,X). AND it with $01 to mask off the default drive bit, and store the result as the current drive number, DRVNUM ($7F) . | |
CDFA | 29 01 | AND #$01 | ||
CDFC | 85 7F | STA $7F | ||
CDFE | BD 87 02 | LDA $0287,X | Move the desired sector from FILSEC+2,X ($0287, X) to SECTOR ($81). | |
CE01 | 85 81 | STA $81 | ||
CE03 | BD 86 02 | LDA $0286,X | Move the desired track from FILSEC+1,X ($0286, X) to TRACK ($80). | |
CE06 | 85 80 | STA $80 | ||
CE08 | 20 5F D5 | JSR $D55F | JSR to TSCHK ($D55F) to test whether the track and sector values are legal. | |
CE0B | 4C 00 C1 | JMP $C100 | JMP to SETLDS to turn on drive active LED. Do RTS from there. | |
Find relative file
|
||||
FNDREL | CE0E | 20 2C CE | JSR $CE2C | JSR to MULPLY($CE2C) to find total bytes TOTAL = REC# x RS + RECPTR |
CE11 | 20 6E CE | JSR $CE6E | JSR to DIV254 to divide by 254. The result is the record's location (in sectors) from the start of the file. | |
CE14 | A5 90 | LDA $90 | Save the remainder (in .A) into RELPTR ($D7). This points into the last sector. | |
CE16 | 85 D7 | STA $D7 | ||
CE18 | 20 71 CE | JSR $CE71 | JSR to DIV120 to divide by 120. The result points into the side sector file. | |
CE1B | E6 D7 | INC $D7 | Increment the pointer into the sector, RELPTR ($D7) by two to bypass the two link bytes at the start of the sector. | |
CE1D | E6 D7 | INC $D7 | ||
CE1F | A5 8B | LDA $8B | Move the quotient of the division by 120 from RESULT ($8B) to SSNUM ($D5). | |
CE21 | 85 D5 | STA $D5 | ||
CE23 | A5 90 | LDA $90 | Load .A with the remainder of the division from ACCUM+1 ($90). multiply it by two (ASL) because each side sector pointer occupies two bytes (t & s). add $10 (#16) to skip the initial link table in the sector, and store the resulting side sector index (points into the sector holding the side sectors) into SSIND ($D6) . | |
CE25 | 0A | ASL | ||
CE26 | 18 | CLC | ||
CE27 | 69 10 | ADC #$10 | ||
CE29 | 85 D6 | STA $D6 | ||
CE2B | 60 | RTS | Terminate routine with an RTS. | |
Calculate a record's location in bytesTOTAL = REC# x RS + RECPTR |
||||
MULPLY | CE2C | 20 D9 CE | JSR $CED9 | JSR to ZERRES ($CED9) to zero the RESULT area ($8B-$8D) . |
CE2F | 85 92 | STA $92 | ||
CE31 | A6 82 | LDX $82 | Zero ACCUM+3 ($92) . | |
CE33 | B5 B5 | LDA $B5,X | Load .X with the LINDX ($82) and use it to move the lo byte of the record number from RECL,X ($B5) to ACCUM+1 ($90). | |
CE35 | 85 90 | STA $90 | ||
CE37 | B5 BB | LDA $BB,X | Move the hi byte of the record number from RECH,X ($BB) to ACCUM+2 ($91) . | |
CE39 | 85 91 | STA $91 | ||
CE3B | D0 04 | BNE $CE41 | If the hi byte of the record number is not $00. branch to MUL25. | |
CE3D | A5 90 | LDA $90 | If the lo byte of the record number is $00. branch to MUL50 to adjust for record #0 (the first record) . | |
CE3F | F0 0B | BEQ $CE4C | ||
MUL25 | CE41 | A5 90 | LDA $90 | Load .A with the lo byte of the record size from ACCUM+1 ($90). set the carry flag, subtract $01, and store the result back in ACCUM+1. If the carry flag is still set, branch to MULT50. |
CE43 | 38 | SEC | ||
CE44 | E9 01 | SBC #$01 | ||
CE46 | 85 90 | STA $90 | ||
CE48 | B0 02 | BCS $CE4C | ||
CE4A | C6 91 | DEC $91 | Decrement the hi byte of the record size in ACCUM+2 ($91) . | |
MUL50 | CE4C | B5 C7 | LDA $C7,X | Copy the record size from RS,X ($C7,X) to TEMP ($6F) . |
CE4E | 85 6F | STA $6F | ||
MUL100 | CE50 | 46 6F | LSR $6F | Do an LSR on TEMP ($6F). If the carry flag is clear, branch to MUL200 (no add this time) . |
CE52 | 90 03 | BCC $CE57 | ||
CE54 | 20 ED CE | JSR $CEED | JSR to ADDRES ($CEED) to add. RESULT = RESULT + ACCUM+1, 2, 3 | |
MUL200 | CE57 | 20 E5 CE | JSR $CEE5 | JSR to ACCX2 ($CEE5) to multiply the ACCUM+1, 2, 3 by two. |
CE5A | A5 6F | LDA $6F | Test TEMP to see if done, if not branch back to MUL100. | |
CE5C | D0 F2 | BNE $CE50 | ||
CE5E | A5 D4 | LDA $D4 | Add the byte pointer to the result. | |
CE60 | 18 | CLC | ||
CE61 | 65 8B | ADC $8B | ||
CE63 | 85 8B | STA $8B | ||
CE65 | 90 06 | BCC $CE6D | ||
CE67 | E6 8C | INC $8C | ||
CE69 | D0 02 | BNE $CE6D | ||
CE6B | E6 8D | INC $8D | ||
MUL400 | CE6D | 60 | RTS | Terminate routine with an RTS. |
Divide routineRESULT ($83) = QUOTIENT ACCUM+1 ($90) = REMAINDER |
||||
Divide by 254 entry point |
||||
DIV254 | CE6E | A9 FE | LDA #$FE | Load .A with $FE (#254) |
CE70 | 2C | Byte $2C (skip over next instruction) | ||
Divide by 120 entry point |
||||
DIV120 | CE71 | A9 78 | LDA #$78 | Load .A with $78 (#120) |
CE73 | 85 6F | STA $6F | Store divisor into TEMP ($6F) . | |
CE75 | A2 03 | LDX #$03 | Swap ACCUM+1 ,2. 3 with RESULT, 1,2 | |
CE77 | B5 8F | LDA $8F,X | ||
CE79 | 48 | PHA | ||
CE7A | B5 8A | LDA $8A,X | ||
CE7C | 95 8F | STA $8F,X | ||
CE7E | 68 | PLA | ||
CE7F | 95 8A | STA $8A,X | ||
CE81 | CA | DEX | ||
CE82 | D0 F3 | BNE $CE77 | ||
CE84 | 20 D9 CE | JSR $CED9 | JSR to ZERRES ($CED9) to zero RESULT, 1,2 | |
DIV150 | CE87 | A2 00 | LDX #$00 | Zero .X |
DIV200 | CE89 | B5 90 | LDA $90,X | Divide by 256 by moving the value in ACCUM+1, X ($90, X) to ACCUM,X ($8F,X). |
CE8B | 95 8F | STA $8F,X | ||
CE8D | E8 | INX | Increment .X. If .X is not 4 yet, branch back to DIV200. | |
CE8E | E0 04 | CPX #$04 | ||
CE90 | 90 F7 | BCC $CE89 | ||
CE92 | A9 00 | LDA #$00 | Zero the hi byte, ACCUM+3 ($92). Check if this is a divide by 120 by testing bit 7 of TEMP. If it is a divide by 254, branch to DIV300. | |
CE94 | 85 92 | STA $92 | ||
CE96 | 24 6F | BIT $6F | ||
CE98 | 30 09 | BMI $CEA3 | ||
CE9A | 06 8F | ASL $8F | Do an ASL of ACCUM ($8F) to set the carry flag if ACCUM > 127. Push the processor status on the stack to save the carry flag. Do an LSR on ACCUM to restore its original value. Pull the processor status back off the stack and JSR to ACC200 ($CEE6) to multiply the value in the ACCUM, 1,2 by two so that we have, in effect, divided by 128.
| |
CE9C | 08 | PHP | ||
CE9D | 46 8F | LSR $8F | ||
CE9F | 28 | PLP | ||
CEA0 | 20 E6 CE | JSR $CEE6 | ||
DIV300 | CEA3 | 20 ED CE | JSR $CEED | JSR to ADDRES ($CEED) to add the ACCUM to the RESULT. |
CEA6 | 20 E5 CE | JSR $CEE5 | JSR to ACCX2 ($CEE5) to multiply the ACCUM by two. | |
CEA9 | 24 6F | BIT $6F | Check if this is a divide by 120 by testing bit 7 of TEMP. If it is a divide by 254, branch to DIV400. | |
CEAB | 30 03 | BMI $CEB0 | ||
CEAD | 20 E2 CE | JSR $CEE2 | JSR to ACCX4 ($CEE2) to multiply the ACCUM by four. A= 4 * (2 * A) = 8 * A | |
DIV400 | CEB0 | A5 8F | LDA $8F | Add in the remainder from ACCUM ($8F) to ACCUM+1. If a carry is produced, increment ACCUM+2 and, if necessary, ACCUM+3. |
CEB2 | 18 | CLC | ||
CEB3 | 65 90 | ADC $90 | ||
CEB5 | 85 90 | STA $90 | ||
CEB7 | 90 06 | BCC $CEBF | ||
CEB9 | E6 91 | INC $91 | ||
CEBB | D0 02 | BNE $CEBF | ||
CEBD | E6 92 | INC $92 | ||
DIV500 | CEBF | A5 92 | LDA $92 | Test if remainder is less than 256 by ORing ACCUM+3 and ACCUM+2. If the result is not zero, the remainder is too large so branch to DIV to crunch some more. |
CEC1 | 05 91 | ORA $91 | ||
CEC3 | D0 C2 | BNE $CE87 | ||
CEC5 | A5 90 | LDA $90 | Test if remainder is less than divisor subtracting the divisor, TEMP ($6F) from the remainder in ACCUM+1 ($90). If the remainder is smaller, branch to DIV600. | |
CEC7 | 38 | SEC | ||
CEC8 | E5 6F | SBC $6F | ||
CECA | 90 0C | BCC $CED8 | ||
CECC | E6 8B | INC $8B | ||
CECE | D0 06 | BNE $CED6 | ||
CED0 | E6 8C | INC $8C | Since the remainder is too large, add 1 to the RESULT. | |
CED2 | D0 02 | BNE $CED6 | ||
CED4 | E6 8D | INC $8D | ||
DIV600 | CED6 | 85 90 | STA $90 | Store the new, smaller remainder in ACCUM+1 ($90) . |
CED8 | 60 | RTS | Terminate routine with an RTS. | |
Zero the RESULT area |
||||
ZERRES | CED9 | A9 00 | LDA #$00 | Load .A with $00 and store in RESULT ($8B), RESULT+1 ($8C). and RESULT+2 ($8D) |
CEDB | 85 8B | STA $8B | ||
CEDD | 85 8C | STA $8C | ||
CEDF | 85 8D | STA $8D | ||
CEE1 | 60 | RTS | Terminate routine with an RTS. | |
Multiply ACCUM by 4 |
||||
ACCX4 | CEE2 | 20 E5 CE | JSR $CEE5 | JSR ACCX2 ($CEE5) |
Multiply ACCUM by 2 |
||||
ACCX2 | CEE5 | 18 | CLC | Clear the carry flag. |
ACC200 | CEE6 | 26 90 | ROL $90 | Do a ROL on ACCUM+1 ( $90 ). ACCUM+2 ( $91 ) , and ACCUM+2 ($92) . |
CEE8 | 26 91 | ROL $91 | ||
CEEA | 26 92 | ROL $92 | ||
CEEC | 60 | RTS | Terminate routine with an RTS. | |
Add ACCUM to RESULT |
||||
ADDRES | CEED | 18 | CLC | Load .X with $FD. |
CEEE | A2 FD | LDX #$FD | ||
ADD100 | CEF0 | B5 8E | LDA $8E,X | Add RESULT+3,X ($8E,X) and ACCUM+4,X ($93) and store the result in RESULT+3, |
CEF2 | 75 93 | ADC $93,X | ||
CEF4 | 95 8E | STA $8E,X | ||
CEF6 | E8 | INX | Increment .X. If not $00 yet, branch back to ADD100. | |
CEF7 | D0 F7 | BNE $CEF0 | ||
CEF9 | 60 | RTS | Terminate routine with an RTS. | |
Initialize LRU (least recently used) table |
||||
LRUINT | CEFA | A2 00 | LDX #$00 | Load .X with $00. |
LRUILP | CEFC | 8A | TXA | Transfer .X to .A. Store the value in .A into LRUTBL,X ($FA,X). |
CEFD | 95 FA | STA $FA,X | ||
CEFF | E8 | INX | Increment .X and compare it to $04, the command channel number. If not yet equal, branch back to LRUILP. | |
CF00 | E0 04 | CPX #$04 | ||
CF02 | D0 F8 | BNE $CEFC | ||
CF04 | A9 06 | LDA #$06 | Load .A with $06, the BAM logical index for the floating BAM, and store this value into LRUTBL,X ($FA,X) . | |
CF06 | 95 FA | STA $FA,X | ||
CF08 | 60 | RTS | Terminate routine with an RTS. | |
Update LRU (least recently used) table |
||||
LRUUPD | CF09 | A0 04 | LDY #$04 | Load .Y with $04, the command channel number. Load .X from LINDX ($82) the current channel number. |
CF0B | A6 82 | LDX $82 | ||
LRULP1 | CF0D | B9 FA 00 | LDA $00FA,Y | Load .A with the value from LRUTBL,Y ($00FA,Y). Store the current channel number (from .X) into LRUTBL,Y. |
CF10 | 96 FA | STX $FA,Y | ||
CF12 | C5 82 | CMP $82 | Compare the value in .A with the current channel number in LINDX ($82). If they are equal, branch to LRUEXT to exit. | |
CF14 | F0 07 | BEQ $CF1D | ||
CF16 | 88 | DEY | Decrement .Y the channel counter. If no more channels to do (Y<0) branch to LRUINT ($CEFA) since no match was found. | |
CF17 | 30 E1 | BMI $CEFA | ||
CF19 | AA | TAX | Transfer .A to .X and JMP to LRULPl .A into LRUTBL,X ($FA,X) . | |
CF1A | 4C 0D CF | JMP $CF0D | ||
LRUEXT | CF1D | 60 | RTS | Terminate routine with an RTS. |
Double buffer: switch the active and inactive buffers. |
||||
DBLBUF | CF1E | 20 09 CF | JSR $CF09 | JSR to LRUUPD ($CF09) to update the LRU (least recently used) table. |
CF21 | 20 B7 DF | JSR $DFB7 | JSR to GETINA ($DFB7) to get the LINDX channel's inactive buffer number (in .A) | |
CF24 | D0 46 | BNE $CF6C | On return, if there is an inactive buffer, branch to DBL15. | |
CF26 | 20 D3 D1 | JSR $D1D3 | There is no inactive buffer so make one I JSR to SETDRN ($D1D3) to set the drive number to the one in LSTJOB. | |
CF29 | 20 8E D2 | JSR $D28E | JSR to GETBUF ($D28E) to get a free buffer number. If no buffers available, branch to DBL30 and abort. | |
CF2C | 30 48 | BMI $CF76 | ||
CF2E | 20 C2 DF | JSR $DFC2 | JSR to PUTINA ($DFC2) to store the new buffer number as the inactive buffer. | |
CF31 | A5 80 | LDA $80 | Save the current values of TRACK ($80) and SECTOR ($81) on the stack. | |
CF33 | 48 | PHA | ||
CF34 | A5 81 | LDA $81 | ||
CF36 | 48 | PHA | ||
CF37 | A9 01 | LDA #$01 | Load .A with $01 and JSR to DRDBYT ($D4F6) to direct read .A bytes. Store the byte read as the current SECTOR ($81) | |
CF39 | 20 F6 D4 | JSR $D4F6 | ||
CF3C | 85 81 | STA $81 | ||
CF3E | A9 00 | LDA #$00 | Load .A with $00 and JSR to DRDBYT ($D4F6) to direct read .A bytes. Store the byte read as the current TRACK($80). | |
CF40 | 20 F6 D4 | JSR $D4F6 | ||
CF43 | 85 80 | STA $80 | ||
CF45 | F0 1F | BEQ $CF66 | If the TRACK byte was $00 (last sector in the file), branch to DBL10. | |
CF47 | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to determine the file type we are working on. If it is a relative file, branch to DBL05. | |
CF4A | F0 0B | BEQ $CF57 | ||
CF4C | 20 AB DD | JSR $DDAB | JSR to TSTWRT ($DDAB) to see if we are writing this file or just reading it. If just reading, branch to DBL05 to read ahead. | |
CF4F | D0 06 | BNE $CF57 | ||
CF51 | 20 8C CF | JSR $CF8C | We are writing so JSR to TGLBUF ($CF8C) to toggle the buffers. On return, JMP to DBL08. | |
CF54 | 4C 5D CF | JMP $CF5D | ||
DBL05 | CF57 | 20 8C CF | JSR $CF8C | JSR to TGLBUF ($CF8C) to toggle the inactive and inactive buffers. |
CF5A | 20 57 DE | JSR $DE57 | JSR to RDAB ($DE57) to read in the next sector of the file (into active buffer) . | |
DBL08 | CF5D | 68 | PLA | Pull the old SECTOR($81) and TRACK ($80) values from the stack and restore them. |
CF5E | 85 81 | STA $81 | ||
CF60 | 68 | PLA | ||
CF61 | 85 80 | STA $80 | ||
CF63 | 4C 6F CF | JMP $CF6F | JMP to DBL20. | |
DBL10 | CF66 | 68 | PLA | Pull the old SECTOR($81) and TRACK ($80) values from the stack and restore them. |
CF67 | 85 81 | STA $81 | ||
CF69 | 68 | PLA | ||
CF6A | 85 80 | STA $80 | ||
DBL15 | CF6C | 20 8C CF | JSR $CF8C | JSR to TGLBUF ($CF8C) to toggle the inactive and active buffers. |
DBL20 | CF6F | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A). Transfer the active buffer number into .X and JMP to WATJOB ($D599) to wait until job is done |
CF72 | AA | TAX | ||
CF73 | 4C 99 D5 | JMP $D599 | ||
DBL30 | CF76 | A9 70 | LDA #$70 | No buffers to steal so load .A with $70 to indicate a NO CHANNEL error and JMP to CMDERR ($C1C8) . |
CF78 | 4C C8 C1 | JMP $C1C8 | ||
Set up double buffering |
||||
DBSET | CF7B | 20 09 CF | JSR $CF09 | JSR to LRUUPD ($CF09) to update the LRU (least recently used) table. |
CF7E | 20 B7 DF | JSR $DFB7 | JSR to GETINA ($DFB7) to get the number of the inactive buffer (in .A) . | |
CF81 | D0 08 | BNE $CF8B | If there is an inactive buffer, branch to DBS10 to exit. | |
CF83 | 20 8E D2 | JSR $D28E | JSR to GETBUF ($DF93) to find an unused buffer. If no buffers available, branch to DBL30 ($CF76) to abort. | |
CF86 | 30 EE | BMI $CF76 | ||
CF88 | 20 C2 DF | JSR $DFC2 | JSR to PUTINA ($DFC2) to set the buffer found as the inactive buffer. | |
DBS10 | CF8B | 60 | RTS | Terminate routine with an RTS. |
Toggle the inactive & active buffersInput: LINDX = current channel # |
||||
TGLBUF | CF8C | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) and use it as an index to load .A with the buffer number from BUF0,X ($A7). EOR this number with $80 to change its active/ inactive state and store the modified value back in BUF0,X, |
CF8E | B5 A7 | LDA $A7,X | ||
CF90 | 49 80 | EOR #$80 | ||
CF92 | 95 A7 | STA $A7,X | ||
CF94 | B5 AE | LDA $AE,X | Load .A with the buffer number from BUF1,X ($AE). EOR this number with $80 to change its active/inactive state and store the modified value back in BUF1,X, | |
CF96 | 49 80 | EOR #$80 | ||
CF98 | 95 AE | STA $AE,X | ||
CF9A | 60 | RTS | Terminate routine with an RTS. | |
Write byte to internal write channel |
||||
PIBYTE | CF9B | A2 12 | LDX #$12 | Load .X with $12 (#18) the secondary address of the internal write channel and use it to set the current secondary address SA ($83) . |
CF9D | 86 83 | STX $83 | ||
CF9F | 20 07 D1 | JSR $D107 | JSR to FNDWCH ($D107) to find an unused write channel. | |
CFA2 | 20 00 C1 | JSR $C100 | JSR to SETLED ($C100) to turn on the drive active LED. | |
CFA5 | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to determine the current file type. If NOT a relative file, branch to PBYTE ($CFAF) . | |
CFA8 | 90 05 | BCC $CFAF | ||
CFAA | A9 20 | LDA #$20 | Load .A with $20 (the overflow flag bit) and JSR to CLRFLG ($DD9D) to clear the overflow flag. | |
CFAC | 20 9D DD | JSR $DD9D | ||
Write byte to any channel |
||||
PBYTE | CFAF | A5 83 | LDA $83 | Load .A with the current secondary address from SA ($83). Compare the SA with $0F (#15) to see if we are using the command channel. If SA=$0F, this is the command channel so branch to L42 ($CFD8). If not, branch to L40 ($CFBF). |
CFB1 | C9 0F | CMP #$0F | ||
CFB3 | F0 23 | BEQ $CFD8 | ||
CFB5 | D0 08 | BNE $CFBF | ||
Main routine to write to a channel |
||||
PUT | CFB7 | A5 84 | LDA $84 | Check if this is the command channel or a data channel by loading the original secondary address from ORGSA ($84) , ANDing it with $8F, and comparing the result with $0F (#15). If less than 15, this is a data channel so branch to L42. |
CFB9 | 29 8F | AND #$8F | ||
CFBB | C9 0F | CMP #$0F | ||
CFBD | B0 19 | BCS $CFD8 | ||
L40 | CFBF | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to determine the file type. If we are NOT working on a sequential file, branch to L41. |
CFC2 | B0 05 | BCS $CFC9 | ||
CFC4 | A5 85 | LDA $85 | Since this is a sequential file, load .A with the data byte from DATA ($85) and JMP to WRTBYT ($D19D) to write the byte to the channel. | |
CFC6 | 4C 9D D1 | JMP $D19D | ||
L41 | CFC9 | D0 03 | BNE $CFCE | If Z flag not set, we are writing to a true random access file (USR) so branch to L46. |
CFCB | 4C AB E0 | JMP $E0AB | We are writing to a relative (REL) file so JMP to WRTREL ($E0AB) . | |
L46 | CFCE | A5 85 | LDA $85 | Since this is a USR file, load .A with the data byte from DATA ($85) and JSR to PUTBYT ($CFF1) to write it to the channel . |
CFD0 | 20 F1 CF | JSR $CFF1 | ||
CFD3 | A4 82 | LDY $82 | To prepare to write the next byte: load .Y with the channel number from LINDX ($82) and JMP to RNGET2 ($D3EE). | |
CFD5 | 4C EE D3 | JMP $D3EE | ||
L42 | CFD8 | A9 04 | LDA #$04 | Since this is the command channel, set LINDX ($82) to $04 (the command channel number) . |
CFDA | 85 82 | STA $82 | ||
CFDC | 20 E8 D4 | JSR $D4E8 | Test if command buffer is full by doing a JSR to GETPNT ($D4E8) to get the position of the last byte written and comparing it to $2A. If they are equal, the buffer is full so branch to L50. | |
CFDF | C9 2A | CMP #$2A | ||
CFE1 | F0 05 | BEQ $CFE8 | ||
CFE3 | A5 85 | LDA $85 | Since there is space, load .A with the command message byte from DATA ($85) and JSR to PUTBYT ($CFF1) to write it to the command channel. | |
CFE5 | 20 F1 CF | JSR $CFF1 | ||
L50 | CFE8 | A5 F8 | LDA $F8 | Test if this is the last byte of the message by checking the EOIFLG ($F8) . If it is zero, this is the last byte so branch to L45. |
CFEA | F0 01 | BEQ $CFED | ||
CFEC | 60 | RTS | Terminate command with an RTS. | |
L45 | CFED | EE 55 02 | INC $0255 | Increment CMDWAT ($0255) to set the command-waiting flag. |
CFF0 | 60 | RTS | Terminate command with an RTS. | |
PUTBYT | CFF1 | 48 | PHA | Put byte in .A into the active buffer of the channel in LINDX: Save byte in .A onto the stack. |
CFF2 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A). If there is an active buffer, branch to PUTB1. | |
CFF5 | 10 06 | BPL $CFFD | ||
CFF7 | 68 | PLA | No active buffer so pull the data byte off the stack, load .A with $61 to indicate a FILE NOT OPEN error, and JMP to CMDERR ($C1C8) . | |
CFF8 | A9 61 | LDA #$61 | ||
CFFA | 4C C8 C1 | JMP $C1C8 | ||
PUTB1 | CFFD | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer this value to .X |
CFFE | AA | TAX | ||
CFFF | 68 | PLA | Pull the data byte off the stack and store it in the buffer at (BUFTAB,X) ($99, X) . | |
D000 | 81 99 | STA ($99,X) | ||
D002 | F6 99 | INC $99,X | Increment the buffer pointer BUFTAB,X | |
|
||||
D004 | 60 | RTS | Terminate routine with an RTS. | |
Initialize drive(s): (Disk command) |
||||
INTDRV | D005 | 20 D1 C1 | JSR $C1D1 | JSR to SIMPRS ($C1D1) to parse the disk command. |
D008 | 20 42 D0 | JSR $D042 | JSR to INITDR ($D042) to initialize the drive (s) . | |
ID20 | D00B | 4C 94 C1 | JMP $C194 | Terminate command with a JMP to ENDCMD ($C194) . |
Initialize drive given in DRVNUM |
||||
ITRIAL | D00E | 20 0F F1 | JSR $F10F | JSR to BAM2A ($F10F) to get the current BAM pointer in .A. |
D011 | A8 | TAY | Transfer the BAM pointer to .Y and use it as an index to load the BAM LINDX from BUF0,Y ($A7,Y) into .X. If there is a valid buffer number for the BAM (not $FF). branch to IT30. | |
D012 | B6 A7 | LDX $A7,Y | ||
D014 | E0 FF | CPX #$FF | ||
D016 | D0 14 | BNE $D02C | ||
D018 | 48 | PHA | No buffer so we had better get one! Save the BAM pointer in .A on the stack and JSR to GETBUF ($D28E) to find an unused buffer. If a buffer is available, branch to IT20. | |
D019 | 20 8E D2 | JSR $D28E | ||
D01C | AA | TAX | ||
D01D | 10 05 | BPL $D024 | ||
D01F | A9 70 | LDA #$70 | No buffer available so load .A with $70 to indicate a NO CHANNEL error and JSR to CMDER3 ($E648) . | |
D021 | 20 48 E6 | JSR $E648 | ||
IT20 | D024 | 68 | PLA | Pull the BAM pointer from the stack and transfer it to .Y. Transfer the new buffer number from .X to .A, OR it with $80 (to indicate an inactive status) , and store the result in BUF0,Y ($00A7,Y) to allocate the buffer. |
D025 | A8 | TAY | ||
D026 | 8A | TXA | ||
D027 | 09 80 | ORA #$80 | ||
D029 | 99 A7 00 | STA $00A7,Y | ||
IT30 | D02C | 8A | TXA | Transfer the buffer number from .X to .A, AND it with $0F to mask off the inactive status bit, and store it in JOBNUM ($F9) . |
D02D | 29 0F | AND #$0F | ||
D02F | 85 F9 | STA $F9 | ||
D031 | A2 00 | LDX #$00 | Set SECTOR ($81) to $00 and TRACK ($80) to $12 (#18) to prepare to read the BAM. | |
D033 | 86 81 | STX $81 | ||
D035 | AE 85 FE | LDX $FE85 | ||
D038 | 86 80 | STX $80 | ||
D03A | 20 D3 D6 | JSR $D6D3 | JSR to SETH ($D6D3) to set up the seek image of the BAM header. | |
D03D | A9 B0 | LDA #$B0 | Load .A with $B0 (the job code for a SEEK) and JMP to DOJOB ($D58C) to do the seek to track 18. Does an RTS when done. | |
D03F | 4C 8C D5 | JMP $D58C | ||
Initialize drive |
||||
INITDR | D042 | 20 D1 F0 | JSR $F0D1 | JSR to CLNBAM ($F0D1) to zero the track numbers for the BAM. |
D045 | 20 13 D3 | JSR $D313 | JSR to CLDCHN ($D313) to allocate a channel for the BAM. | |
D048 | 20 0E D0 | JSR $D00E | JSR to ITRIAL ($D00E) to allocate a buffer for the BAM and seek track 18. | |
D04B | A6 7F | LDX $7F | ||
D04D | A9 00 | LDA #$00 | Store $00 in MDIRTY,X ($0251) to indicate that the BAM for drive .X is NOT DIRTY (BAM in memory matches BAM on the diskette) . | |
D04F | 9D 51 02 | STA $0251,X | ||
D052 | 8A | TXA | Set the master ID for the diskette in DSKID,X ($12/3 for drive 0) from the track 18 header values ($16/17) read during the seek to track 18 | |
D053 | 0A | ASL | ||
D054 | AA | TAX | ||
D055 | A5 16 | LDA $16 | ||
D057 | 95 12 | STA $12,X | ||
D059 | A5 17 | LDA $17 | ||
D05B | 95 13 | STA $13,X | ||
D05D | 20 86 D5 | JSR $D586 | JSR to DOREAD ($D586) to read the BAM into the buffer. | |
D060 | A5 F9 | LDA $F9 | Load the disk version (#65 for 4040/1541) from the $0X02 position in the BAM and store it in DSKVER,X ($0101 drive number), | |
D062 | 0A | ASL | ||
D063 | AA | TAX | ||
D064 | A9 02 | LDA #$02 | ||
D066 | 95 99 | STA $99,X | ||
D068 | A1 99 | LDA ($99,X) | ||
D06A | A6 7F | LDX $7F | ||
D06C | 9D 01 01 | STA $0101,X | ||
D06F | A9 00 | LDA #$00 | Zero WPSW,X ($1C,X) to clear the write protect switch and NODRV,X ($FF,X) to clear the drive-not-active flag. | |
D071 | 95 1C | STA $1C,X | ||
D073 | 95 FF | STA $FF,X | ||
NFCALC | D075 | 20 3A EF | JSR $EF3A | Count the number of free blocks in BAM JSR to SETBPT ($EF3A) to set the bit map pointer and read in the BAM if necessary |
D078 | A0 04 | LDY #$04 | Initialize .Y to $04 and zero .A and .X (.X will be the hi byte of the count). | |
D07A | A9 00 | LDA #$00 | ||
D07C | AA | TAX | ||
NUMF1 | D07D | 18 | CLC | Clear carry and add (BMPNT) ,Y; ($6D),Y to the value in .A. If no carry, branch to NUMF2. |
D07E | 71 6D | ADC ($6D),Y | ||
D080 | 90 01 | BCC $D083 | ||
D082 | E8 | INX | Increment .X (the hi byte of the count) . | |
NUMF2 | D083 | C8 | INY | Increment .Y four times so it points to the start of the next track byte in the BAM. Compare .Y to $48 (the directory track location). If .Y=$48, branch to NUMF2 to skip the directory track. |
D084 | C8 | INY | ||
D085 | C8 | INY | ||
D086 | C8 | INY | ||
D087 | C0 48 | CPY #$48 | ||
D089 | F0 F8 | BEQ $D083 | ||
D08B | C0 90 | CPY #$90 | Compare .Y to $90 to see if we are done. If there is more to do, branch to NUMF1. | |
D08D | D0 EE | BNE $D07D | ||
D08F | 48 | PHA | All done. Save the lo byte of the count on the stack and transfer the hi byte from .X to .A. Load .X with the current drive number from DRVNUM ($7F) and store the hi byte of the count (in .A) into NDBH,X ($02FC,X). Pull the lo byte of the count off the stack and save it in NDBL,X ($02FA,X) . | |
D090 | 8A | TXA | ||
D091 | A6 7F | LDX $7F | ||
D093 | 9D FC 02 | STA $02FC,X | ||
D096 | 68 | PLA | ||
D097 | 9D FA 02 | STA $02FA,X | ||
D09A | 60 | RTS | Terminate routine with an RTS. | |
Start reading ahead |
||||
STRRD | D09B | 20 D0 D6 | JSR $D6D0 | Use the values in TRACK and SECTOR to read a data block. Use the track and sector pointers to set up the next one. JSR to SETHDR ($D6D0) to set up the header image using TRACK ($80) and SECTOR ($8i) values. |
D09E | 20 C3 D0 | JSR $D0C3 | JSR to RDBUF ($D0C3) to read the first block into the data buffer. | |
D0A1 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the read job to be completed. | |
D0A4 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to get the first byte from the data buffer (track link) and store it in TRACK ($80) . | |
D0A7 | 85 80 | STA $80 | ||
D0A9 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to get the second byte from the data buffer (sector link) and store it in SECTOR ($81). | |
D0AC | 85 81 | STA $81 | ||
D0AE | 60 | RTS | Terminate routine with an RTS. | |
Start double buffering: (reading ahead) |
||||
STRDBL | D0AF | 20 9B D0 | JSR $D09B | JSR to STRRD ($D09B) to read in a data block and set up the next one. |
D0B2 | A5 80 | LDA $80 | Check the current TRACK ($80) value. If not $00. we are not at the end of the file so branch to STR1. | |
D0B4 | D0 01 | BNE $D0B7 | ||
D0B6 | 60 | RTS | Terminate routine with an RTS. | |
STR1 | D0B7 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to set up buffers and pointers for double buffering and set TRACK and SECTOR for the next block, |
D0BA | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0) to set up the header image using TRACK ($80) and SECTOR ($81) values. | |
D0BD | 20 C3 D0 | JSR $D0C3 | JSR to RDBUF ($D0C3) to read the next block into the data buffer. | |
D0C0 | 4C 1E CF | JMP $CF1E | JMP to DBLBUF ($CF1E) to set up buffers and pointers for double buffering and set TRACK and SECTOR for the next block. | |
RDBUF | D0C3 | A9 80 | LDA #$80 | Start a read job of TRACK and SECTOR Load .A with $80. the job code for a read, and branch to STRTIT ($D0C9) . |
D0C5 | D0 02 | BNE $D0C9 | ||
WRTBUF | D0C7 | A9 90 | LDA #$90 | Start a write job of TRACK and SECTOR Load .A with $90, the job code for a write. |
STRTIT | D0C9 | 8D 4D 02 | STA $024D | Store command desired (in .A) as the current command in CMD ($024D) . |
D0CC | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A). Transfer the active buffer number into .X. | |
D0CF | AA | TAX | ||
D0D0 | 20 06 D5 | JSR $D506 | JSR to SETLJB ($D506) to set up drive number (from the last job). check for legal track & sector, and, if all OK, do the job. On return .A=job number and . X=buf fer number. | |
D0D3 | 8A | TXA | Transfer buffer number from .X to .A and save it on the stack. Multiply the buffer number by two (ASL) and transfer the result into .X and use it as an index to store $00 in the buffer table pointer BUFTAB,X ($99, X) | |
D0D4 | 48 | PHA | ||
D0D5 | 0A | ASL | ||
D0D6 | AA | TAX | ||
D0D7 | A9 00 | LDA #$00 | ||
D0D9 | 95 99 | STA $99,X | ||
D0DB | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to get the file type. Compare the file type to $04. If this is not a sequential file, branch to WRTC1. | |
D0DE | C9 04 | CMP #$04 | ||
D0E0 | B0 06 | BCS $D0E8 | ||
D0E2 | F6 B5 | INC $B5,X | Since this is a sequential file, increment the lo byte of the block count in NBKL,X ($B5,X) and, if necessary, the hi byte in NBKH,X ($BB,X) . | |
D0E4 | D0 02 | BNE $D0E8 | ||
D0E6 | F6 BB | INC $BB,X | ||
WRTC1 | D0E8 | 68 | PLA | Pull the original buffer number off the stack and transfer it back into .X. |
D0E9 | AA | TAX | ||
D0EA | 60 | RTS | Terminate routine with an RTS. | |
Find the assigned read channel |
||||
FNDRCH | D0EB | A5 83 | LDA $83 | Compare the current secondary address from SA ($83) with $13 (#19) the highest allowable secondary address+1. If too large, branch to FNDC20. |
D0ED | C9 13 | CMP #$13 | ||
D0EF | 90 02 | BCC $D0F3 | ||
D0F1 | 29 0F | AND #$0F | AND the secondary address with $0F
| |
FNDC20 | D0F3 | C9 0F | CMP #$0F | Compare the sec addr in .A with $0F(15), the command channel sec addr. If they are not equal, branch to FNDC25. |
D0F5 | D0 02 | BNE $D0F9 | ||
D0F7 | A9 10 | LDA #$10 | Load .A with $10, the sec addr error value. | |
FNDC25 | D0F9 | AA | TAX | Transfer the sec addr from .A to .X, set the carry flag, and load the channel number from LINTAB,X ($022B,X). If bit 7 is set, no channel has been assigned for this sec addr, so branch to FNDC30 to exit (with carry bit set). |
D0FA | 38 | SEC | ||
D0FB | BD 2B 02 | LDA $022B,X | ||
D0FE | 30 06 | BMI $D106 | ||
D100 | 29 0F | AND #$0F | AND the current channel number with $0F and store the result as the current channel number in LINDX ($82). Transfer the channel number into .X and clear the carry bit. | |
D102 | 85 82 | STA $82 | ||
D104 | AA | TAX | ||
D105 | 18 | CLC | ||
FNDC30 | D106 | 60 | RTS | Terminate routine with an RTS. |
Find the assigned write channel |
||||
FNDWCH | D107 | A5 83 | LDA $83 | Compare the current secondary address from SA ($83) with $13 (#19) the highest allowable secondary address+1. If too large. branch to FNDW13. |
D109 | C9 13 | CMP #$13 | ||
D10B | 90 02 | BCC $D10F | ||
D10D | 29 0F | AND #$0F | AND the secondary address with $0F
| |
FNDW13 | D10F | AA | TAX | Transfer the sec addr from .A to .X, and load the channel number assigned to this sec addr from LINTAB,X ($022B,X) . |
D110 | BD 2B 02 | LDA $022B,X | ||
D113 | A8 | TAY | Transfer this channel number to .Y. | |
D114 | 0A | ASL | Do an ASL of the channel number in .A. | |
D115 | 90 0A | BCC $D121 | If a channel has been assigned for this sec addr (bit 7 of LINTAB,X is not set) branch to FNDW15. | |
D117 | 30 0A | BMI $D123 | If no channel assigned has been assigned for this secondary address (bit 6 also set). branch to FNDW20 and abort. | |
FNDW10 | D119 | 98 | TYA | Transfer the original sec addr from .Y to .A, AND it with $0F to mask off any high order bits, and store it in LINDX ($82) as the currently active channel. Transfer the channel number to .X, clear the carry flag, and terminate with RTS. |
D11A | 29 0F | AND #$0F | ||
D11C | 85 82 | STA $82 | ||
D11E | AA | TAX | ||
D11F | 18 | CLC | ||
D120 | 60 | RTS | ||
FNDW15 | D121 | 30 F6 | BMI $D119 | If bit 6 of LINTAB,X is set (indicates an inactive channel), branch to FNDW10. |
FNDW20 | D123 | 38 | SEC | Abort by setting the carry flag and terminate the routine with an RTS. |
D124 | 60 | RTS | ||
Get current file type |
||||
TYPFIL | D125 | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . |
D127 | B5 EC | LDA $EC,X | Load .A with the file type from the file type table, FILTYP,X ($EC,X). | |
D129 | 4A | LSR | Divide the file type by 2 (LSR). AND it with $07 to mask off higher order bits, and compare the result with $04 '(set the Z flag if it is a REL file!). | |
D12A | 29 07 | AND #$07 | ||
D12C | C9 04 | CMP #$04 | ||
D12E | 60 | RTS | Terminate the routine with an RTS. | |
Set buffer pointers |
||||
GETPRE | D12F | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A) . |
D132 | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer the result into .X. | |
D133 | AA | TAX | ||
D134 | A4 82 | LDY $82 | Load .Y with the current channel number from LINDX ($82) . | |
D136 | 60 | RTS | Terminate the routine with an RTS. | |
Read one byte from the active buffer |
||||
GETBYT | D137 | 20 2F D1 | JSR $D12F | If last data byte in buffer, set Z flag. JSR to GETPRE to set buffer pointers. |
D13A | B9 44 02 | LDA $0244,Y | Load .A with the pointer to the last character read from LSTCHR,Y ($0244, Y). | |
D13D | F0 12 | BEQ $D151 | If pointer is zero, branch to GETB1. | |
D13F | A1 99 | LDA ($99,X) | Load the data byte from (BUFTAB,X) ($99, X) and save it on the stack. | |
D141 | 48 | PHA | ||
D142 | B5 99 | LDA $99,X | Load the pointer from BUFTAB,X ($99, X) and compare it to the pointer to the last character read in LSTCHR,Y. If the pointers are not equal, branch to GETB2. | |
D144 | D9 44 02 | CMP $0244,Y | ||
D147 | D0 04 | BNE $D14D | ||
D149 | A9 FF | LDA #$FF | Store $FF in BUFTAB,X ($99, X) | |
D14B | 95 99 | STA $99,X | ||
GETB2 | D14D | 68 | PLA | Pull the data byte off the stack and increment BUFTAB,X ($99, X). This will set the Z flag if this is the last byte. |
D14E | F6 99 | INC $99,X | ||
D150 | 60 | RTS | Terminate routine with an RTS. | |
GETB1 | D151 | A1 99 | LDA ($99,X) | Load the data byte from (BUFTAB,X) ($99, X) . |
D153 | F6 99 | INC $99,X | Increment BUFTAB,X ($99, X). | |
D155 | 60 | RTS | Terminate routine with an RTS. | |
Read byte from fileThe next file will be read if necessary and CHNRDY($F2) will be set to EOI if we have read the last character in file. |
||||
RDBYT | D156 | 20 37 D1 | JSR $D137 | JSR to GETBYT to read a byte from the active buffer. On return, if Z flag is not set, we did not read the last byte in the buffer so branch to RD3 and RTS. |
D159 | D0 36 | BNE $D191 | ||
D15B | 85 85 | STA $85 | ||
D15D | B9 44 02 | LDA $0244,Y | ||
D160 | F0 08 | BEQ $D16A | ||
D162 | A9 80 | LDA #$80 | We read the last byte so load .A with $80, the EOI flag. | |
RD01 | D164 | 99 F2 00 | STA $00F2,Y | Store the channel status (in .A) into CHNRDY,Y ($00F2,Y) . |
D167 | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) . | |
D169 | 60 | RTS | Exit from routine with an RTS. | |
RD1 | D16A | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to begin double buffering. |
D16D | A9 00 | LDA #$00 | Load .A with $00 and JSR to SETPNT ($D4C8) to set up the buffer pointers | |
D16F | 20 C8 D4 | JSR $D4C8 | ||
D172 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read the first byte from the active buffer (track link) | |
D175 | C9 00 | CMP #$00 | Compare the track link to $00. If it is $00, there is no next block so branch to RD4. | |
D177 | F0 19 | BEQ $D192 | ||
D179 | 85 80 | STA $80 | There is another block in this file so store the track link in TRACK ($80). | |
D17B | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read the next byte from the active buff er (sector link) and store it in SECTOR ($81). | |
D17E | 85 81 | STA $81 | ||
D180 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to begin double buffering. | |
D183 | 20 D3 D1 | JSR $D1D3 | JSR to SETDRN ($D1D3) to set up the drive number. | |
D186 | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0) to set up the next header image. | |
D189 | 20 C3 D0 | JSR $D0C3 | JSR to RDBUF ($D0C3) to read in the next block in the file. | |
D18C | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active & inactive buffers & read ahead. | |
D18F | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) . | |
RD3 | D191 | 60 | RTS | Exit from routine with an RTS. |
RD4 | D192 | 20 37 D1 | JSR $D137 | JSR to GETBYTE ($D137) to get the next byte . |
D195 | A4 82 | LDY $82 | Load .Y with the current channel number from LINDX ($82) and store the new character as the pointer to the last character read from the data buffer LSTCHR,Y ($0244, Y). | |
D197 | 99 44 02 | STA $0244,Y | ||
D19A | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) . | |
D19C | 60 | RTS | Exit from routine with an RTS. | |
Write character to the active channelIf this fills the buffer, write the data buffer out to disk. |
||||
WRTBYT | D19D | 20 F1 CF | JSR $CFF1 | JSR to PUTBYT ($CFF1) to write the byte to the active channel. |
D1A0 | F0 01 | BEQ $D1A3 | If Z flag is set on return, the buffer is full so branch to WRTO. | |
D1A2 | 60 | RTS | Exit from routine with an RTS. | |
WRT0 | D1A3 | 20 D3 D1 | JSR $D1D3 | JSR to SETDRN ($D1D3) to set the current drive number from the one in LSTJOB. |
D1A6 | 20 1E F1 | JSR $F11E | JSR to NXTTS ($F11E) to get the next available track and sector. | |
D1A9 | A9 00 | LDA #$00 | Load .A with $00 and JSR to SETPNT ($D4C8) to set up the buffer pointers. | |
D1AB | 20 C8 D4 | JSR $D4C8 | Load .A with the next available track from TRACK ($80) and JSR to PUTBYT ($CFF1) to store the track link. | |
D1AE | A5 80 | LDA $80 | ||
D1B0 | 20 F1 CF | JSR $CFF1 | ||
D1B3 | A5 81 | LDA $81 | Load .A with the next available sector from SECTOR ($81) and JSR to PUTBYT ($CFF1) to store the sector link. | |
D1B5 | 20 F1 CF | JSR $CFF1 | ||
D1B8 | 20 C7 D0 | JSR $D0C7 | JSR to WRTBUF ($D0C7) to write out the buffer to disk. | |
D1BB | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers and set up the next inactive buffer. | |
D1BE | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0) to set up the header image for the next block. | |
D1C1 | A9 02 | LDA #$02 | Load .A with $02 (to bypass the track and sector link) and JMP to SETPNT to set up the pointers to the next buffer. | |
D1C3 | 4C C8 D4 | JMP $D4C8 | ||
INCPTR | D1C6 | 85 6F | STA $6F | Increment the pointer of the active buffer by .A Store the value from .A in TEMP ($6F) . |
D1C8 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to get the active buffer pointer (in .A). | |
D1CB | 18 | CLC | Clear the carry flag and add the value from TEMP ($6F). Store the result into BUFTAB,X ($99', X) and into DIRBUF ($94). | |
D1CC | 65 6F | ADC $6F | ||
D1CE | 95 99 | STA $99,X | ||
D1D0 | 85 94 | STA $94 | ||
D1D2 | 60 | RTS | Terminate routine with an RTS. | |
Set drive numberSets DRVNUM to the same drive as was used on the last job for the active buffer. |
||||
SETDRN | D1D3 | 20 93 DF | JSR $DF93 | JSR to GETACT ($D4E8) to get the active buffer number (in .A). |
D1D6 | AA | TAX | Transfer the buffer number to .X and use it as an index to load the last job number from LSTJOB,X ($025B) into .A. | |
D1D7 | BD 5B 02 | LDA $025B,X | ||
D1DA | 29 01 | AND #$01 | AND the job number with $01 to mask off all but the drive number bit and store the result as the current drive number in DRVNUM ($7F) . | |
D1DC | 85 7F | STA $7F | ||
D1DE | 60 | RTS | Terminate routine with an RTS. | |
Open a new write channel.A = number of buffers needed The routine allocates a buffer number and sets the logical file index, LINDX. |
||||
GETWCH | D1DF | 38 | SEC | Set the carry flag to indicate that we want a write channel. |
D1E0 | B0 01 | BCS $D1E3 | Branch to GETR2 . | |
Open a new read channel.A = number of buffers needed The routine allocates a buffer number and sets the channel*, LINDX. |
||||
GETRCH | D1E2 | 18 | CLC | Clear the carry flag to indicate that we want a read channel. |
GETR2 | D1E3 | 08 | PHP | Save the processor status (the carry flag) onto the stack. |
D1E4 | 85 6F | STA $6F | Save the number of buffer needed (in .A) into TEMP ($6F) . | |
D1E6 | 20 27 D2 | JSR $D227 | JSR to FRECHN ($D227) to free any channels associated with this secondary address . | |
D1E9 | 20 7F D3 | JSR $D37F | JSR to FNDLNX ($D37F) to find the next free logical index (channel) to use and allocate it. | |
D1EC | 85 82 | STA $82 | Store the new channel number in LINDX as the current channel number. | |
D1EE | A6 83 | LDX $83 | Load .X with the current secondary address from SA ($83) . | |
D1F0 | 28 | PLP | Pull the processor status off the stack and if carry flag is clear (read) , branch to GETR55. | |
D1F1 | 90 02 | BCC $D1F5 | ||
GETR52 | D1F3 | 09 80 | ORA #$80 | OR the channel number in .A with $80 to set bit 7 to indicate a write file. |
GETR55 | D1F5 | 9D 2B 02 | STA $022B,X | Store the channel number (in .A) into the logical index table, LINTAB,X ($022B,X) . NOTE: Bit 7 set for a write channel |
D1F8 | 29 3F | AND #$3F | AND the channel number in .A with $3F to mask off the write channel bit and transfer the result to .Y. | |
D1FA | A8 | TAY | ||
D1FB | A9 FF | LDA #$FF | De-allocate any buffers associated with this channel by storing $FF in BUF0,Y ($00A7,Y), in BUF1,Y ($00AE,Y), and in SS,Y ($00CD,Y) . | |
D1FD | 99 A7 00 | STA $00A7,Y | ||
D200 | 99 AE 00 | STA $00AE,Y | ||
D203 | 99 CD 00 | STA $00CD,Y | ||
GETR3 | D206 | C6 6F | DEC $6F | Decrement the value in TEMP ($6F). This is the number of buffers to allocate. If there are no more to allocate ($FF) , branch to GETR4 and exit. |
D208 | 30 1C | BMI $D226 | ||
D20A | 20 8E D2 | JSR $D28E | JSR to GETBUF ($D28E) to allocate a new buffer. If a buffer was allocated, branch to GETR5 . | |
D20D | 10 08 | BPL $D217 | ||
GETERR | D20F | 20 5A D2 | JSR $D25A | No buffers available, so JSR to RELBUF ($D25A) to release any buffers allocated |
D212 | A9 70 | LDA #$70 | Load .A with $70 to indicate a NO CHANNEL error and JMP to CMDERR ($C1C8). | |
D214 | 4C C8 C1 | JMP $C1C8 | ||
GETR5 | D217 | 99 A7 00 | STA $00A7,Y | Store the buffer number (in .A) into BUF0,Y ($00A7,Y) . |
D21A | C6 6F | DEC $6F | Decrement the value in TEMP ($6F). This is the number of buffers to allocate. If there are no more to allocate ($FF) , branch to GETR4 and exit. | |
D21C | 30 08 | BMI $D226 | ||
D21E | 20 8E D2 | JSR $D28E | JSR to GETBUF ($D28E) to allocate a new buffer. If a buffer was NOT allocated, branch to GETERR and abort. | |
D221 | 30 EC | BMI $D20F | ||
D223 | 99 AE 00 | STA $00AE,Y | Store the buffer number (in .A) into BUF1,Y ($00AE,Y) . | |
GETR4 | D226 | 60 | RTS | Terminate routine with an RTS. |
Free channel associated with SARead and write channels are freed. The command channel is not freed. |
||||
FRECHN | D227 | A5 83 | LDA $83 | Load .A with the secondary address from SA ($83). Compare it with $0F (#15), the command channel secondary address. If the secondary address is not $0F, branch to FRECO. |
D229 | C9 0F | CMP #$0F | ||
D22B | D0 01 | BNE $D22E | ||
D22D | 60 | RTS | Since we are not to free the command channel, simply exit with an RTS. | |
Free data channel associated with SA |
||||
FRECO | D22E | A6 83 | LDX $83 | Load .X with the secondary address from SA ($83) . |
D230 | BD 2B 02 | LDA $022B,X | Load .A with the channel number associated with this secondary address from LINTAB,X ($022B,X). If it is $FF, there is no associated channel so branch to FRE25 and exit. | |
D233 | C9 FF | CMP #$FF | ||
D235 | F0 22 | BEQ $D259 | ||
D237 | 29 3F | AND #$3F | AND the channel number with $3F to mask off the higher order bits and store the result as the current channel in LINDX ($82) . | |
D239 | 85 82 | STA $82 | ||
D23B | A9 FF | LDA #$FF | Free the channel by storing $FF into LINTAB,X ($022B,X) . | |
D23D | 9D 2B 02 | STA $022B,X | ||
D240 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) and store $00 as the channel status (free) inCHNRDY,X ($F2,Y). | |
D242 | A9 00 | LDA #$00 | ||
D244 | 95 F2 | STA $F2,X | ||
D246 | 20 5A D2 | JSR $D25A | JSR to RELBUF ($D25A) to release buffers | |
RELINX | D249 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) and .A with $01. |
D24B | A9 01 | LDA #$01 | ||
REL15 | D24D | CA | DEX | Decrement .X, the channel number. If it is $FF (no lower channel numbers) , branch to REL10. |
D24E | 30 03 | BMI $D253 | ||
D250 | 0A | ASL | Do an ASL on the value in .A. Note that the bit set shifts left one position each time through the loop. | |
D251 | D0 FA | BNE $D24D | If .A <> f branch to REL15 (always). | |
REL10 | D253 | 0D 56 02 | ORA $0256 | OR the value in the accumulator with LINUSE ($0256) to free the channel (bit = 1 for free; bit = for used) . Store the resulting value back in LINUSE ($0256) . |
D256 | 8D 56 02 | STA $0256 | ||
FRE25 | D259 | 60 | RTS | Terminate routine with an RTS. |
Release buffers associated with channel |
||||
RELBUF | D25A | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
D25C | B5 A7 | LDA $A7,X | Load .A with the buffer number for this channel from BUF0,X ($A7,X). Compare the buffer number with $FF (free). If it is already free, branch to REL1. | |
D25E | C9 FF | CMP #$FF | ||
D260 | F0 09 | BEQ $D26B | ||
D262 | 48 | PHA | Save the buffer number on the stack and store $FF into BUF0,X ($A7,X) to free this buffer. | |
D263 | A9 FF | LDA #$FF | ||
D265 | 95 A7 | STA $A7,X | ||
D267 | 68 | PLA | Pull the buffer number off the stack and JSR to FREBUF ($D2F3) to free the buffer | |
D268 | 20 F3 D2 | JSR $D2F3 | ||
REL1 | D26B | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
D26D | B5 AE | LDA $AE,X | Load .A with the buffer number for this channel from BUFlfX ($AE,X). Compare the buffer number with $FF (free). If it is already free, branch to REL2 . | |
D26F | C9 FF | CMP #$FF | ||
D271 | F0 09 | BEQ $D27C | ||
D273 | 48 | PHA | Save the buffer number on the stack and store $FF into BUF1,X ($AE,X) to free this buffer. | |
D274 | A9 FF | LDA #$FF | ||
D276 | 95 AE | STA $AE,X | ||
D278 | 68 | PLA | Pull the buffer number off the stack and JSR to FREBUF ($D2F3) to free the buffer | |
D279 | 20 F3 D2 | JSR $D2F3 | ||
REL2 | D27C | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
D27E | B5 CD | LDA $CD,X | Load .A with the side sector for this channel from SS f X ($CD,X). Compare the side sector with $FF (free). If it is already free, branch to REL3 . | |
D280 | C9 FF | CMP #$FF | ||
D282 | F0 09 | BEQ $D28D | ||
D284 | 48 | PHA | Save the side sector on the stack and store $FF into SS,X ($CD,X) to free the side sector pointer. | |
D285 | A9 FF | LDA #$FF | ||
D287 | 95 CD | STA $CD,X | ||
D289 | 68 | PLA | Pull the side sector off the stack and JSR to FREBUF ($D2F3) to free any buffer | |
D28A | 20 F3 D2 | JSR $D2F3 | ||
REL3 | D28D | 60 | RTS | Terminate routine with an RTS. |
Get a free buffer number .Y=channelIf successful, initialize JOBS & LSTJOB and return with buffer number in .A. If not successful, .A = $FF; N flag set. |
||||
GETBUF | D28E | 98 | TYA | Save channel number by transferring it from .Y to .A and pushing it on the stack. |
D28F | 48 | PHA | ||
D290 | A0 01 | LDY #$01 | Load .Y with $01 and JSR to FNDBUF ($D2BA) to find a free buffer (# in .X). If one is found, branch to GBF1. | |
D292 | 20 BA D2 | JSR $D2BA | ||
D295 | 10 0C | BPL $D2A3 | ||
D297 | 88 | DEY | Decrement .Y and JSR to FNDBUF ($D2BA) to find a free buffer (# in .X). If one found, branch to GBF1. | |
D298 | 20 BA D2 | JSR $D2BA | ||
D29B | 10 06 | BPL $D2A3 | ||
D29D | 20 39 D3 | JSR $D339 | Can't find a free one so let's try to steal one! JSR to STLBUF ($D339) to try to steal an inactive one. On return, buffer # in .A so transfer it to .X. If we didn't get one, branch to GBF2. | |
D2A0 | AA | TAX | ||
D2A1 | 30 13 | BMI $D2B6 | ||
GBF1 | D2A3 | B5 00 | LDA $00,X | Wait till any job using JOBS,X ($00, X) is completed. |
D2A5 | 30 FC | BMI $D2A3 | ||
D2A7 | A5 7F | LDA $7F | Clear the job queue by setting JOBS,X ($00, X) and LSTJOB, X ($025B,X) to the current drive number using the value from DRVNUM ($7F) . | |
D2A9 | 95 00 | STA $00,X | ||
D2AB | 9D 5B 02 | STA $025B,X | ||
D2AE | 8A | TXA | Transfer the buffer number from .X to .A multiply it by two (ASL). and transfer the result to .Y. | |
D2AF | 0A | ASL | ||
D2B0 | A8 | TAY | ||
D2B1 | A9 02 | LDA #$02 | Store a $02 on BUFTAB,Y ($0099, Y) so the pointer points beyond the track and sector link. | |
D2B3 | 99 99 00 | STA $0099,Y | ||
GBF2 | D2B6 | 68 | PLA | Restore the original .Y value from the stack. |
D2B7 | A8 | TAY | ||
D2B8 | 8A | TXA | Transfer the buffer number from .X to .A to set the N flag if not successful. | |
D2B9 | 60 | RTS | Terminate routine with an RTS. | |
Find a free buffer and set BUFUSE:On entry: .Y = index into BUFUSE: Y=0 buffers 0-7; Y=1 buffers 8-15 If successful, .X = buffer number If not successful, .X = $FF; N flag set |
||||
FNDBUF | D2BA | A2 07 | LDX #$07 | Load .X with $07 (for bit test) |
FB1 | D2BC | B9 4F 02 | LDA $024F,Y | Load .A with BUFUSE, Y ($024F,X). Each bit indicates whether a buffer is free (1) or in use (0). AND this value in .A with the bit mask, BMASK,X ($EFE9,X). Each of these masks has just one bit set. If the result of the AND is $00, we have found a free buffer so branch to FB2. |
D2BF | 3D E9 EF | AND $EFE9,X | ||
D2C2 | F0 04 | BEQ $D2C8 | ||
D2C4 | CA | DEX | Decrement .X to try next buffer. If any left, branch back to FBI. | |
D2C5 | 10 F5 | BPL $D2BC | ||
D2C7 | 60 | RTS | No more buffers to try (.X=$FF) so exit with an RTS. | |
FB2 | D2C8 | B9 4F 02 | LDA $024F,Y | Found a free buffer so let's grab it! Load .A with the value in BUFUSE, Y ($024F,Y), EOR it with the bit map for the free buffer, BMASK,X ($EFE9,X), and store the result back in BUFUSE, Y. |
D2CB | 5D E9 EF | EOR $EFE9,X | ||
D2CE | 99 4F 02 | STA $024F,Y | ||
D2D1 | 8A | TXA | Transfer the buffer number from .X to .A and if .Y is $00, branch to FB3 . | |
D2D2 | 88 | DEY | ||
D2D3 | 30 03 | BMI $D2D8 | ||
D2D5 | 18 | CLC | Since .Y is $01 (never happens on the 1541). we have to add 8 to the buffer number. So: Clear the carry flag and add $08 to the buffer number in .A. | |
D2D6 | 69 08 | ADC #$08 | ||
FB3 | D2D8 | AA | TAX | Transfer the buffer number from .A to .X |
FRI20 | D2D9 | 60 | RTS | Terminate routine with an RTS. |
Free the inactive buffer |
||||
FREIAC | D2DA | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . |
D2DC | B5 A7 | LDA $A7,X | Load .A with the buffer number from BUF0,X ($A7,X). If bit 7 is set, branch to FRI10. | |
D2DE | 30 09 | BMI $D2E9 | ||
D2E0 | 8A | TXA | Transfer the channel number from .X to .A, clear the carry flag, add $07 (the maximum number of channels +1). and transfer the result back into .X. This is the alternate buffer for this channel | |
D2E1 | 18 | CLC | ||
D2E2 | 69 07 | ADC #$07 | ||
D2E4 | AA | TAX | ||
D2E5 | B5 A7 | LDA $A7,X | Load .A with the buffer number from BUF0,X ($A7,X). If bit 7 is NOT set, this buffer is active too so exit to FRI20 (above) . | |
D2E7 | 10 F0 | BPL $D2D9 | ||
FRI10 | D2E9 | C9 FF | CMP #$FF | Compare the buffer number to $FF. If it is $FF, the buffer is free already so exit to FRI20 (above). |
D2EB | F0 EC | BEQ $D2D9 | ||
D2ED | 48 | PHA | Save the buffer number on the stack. | |
D2EE | A9 FF | LDA #$FF | Free the buffer by storing $FF into BUF0,X ($A7,X) . | |
D2F0 | 95 A7 | STA $A7,X | ||
D2F2 | 68 | PLA | Pull the buffer number off the stack. | |
Free buffer in BUFUSE |
||||
FREBUF | D2F3 | 29 0F | AND #$0F | AND the buffer number with $0F to mask off any higher order bits, transfer the result into .Y and increment .Y by 1. |
D2F5 | A8 | TAY | ||
D2F6 | C8 | INY | ||
D2F7 | A2 10 | LDX #$10 | Load .X with $10 (#16) 2*8 bits | |
FREB1 | D2F9 | 6E 50 02 | ROR $0250 | Loop to ROR BUFUSE+1 ($0250) and BUFUSE ($024F) 16 times. Use .Y to count down to 0. When .Y is zero, the bit that corresponds to the buffer we want is in the carry flag so we clear the carry bit to free that buffer. We then keep looping until .X has counted down all the way from $10 to $FF. When .X reaches $FF, the bits are all back in the right places, so exit with an RTS. |
D2FC | 6E 4F 02 | ROR $024F | ||
D2FF | 88 | DEY | ||
D300 | D0 01 | BNE $D303 | ||
D302 | 18 | CLC | ||
D303 | CA | DEX | ||
D304 | 10 F3 | BPL $D2F9 | ||
D306 | 60 | RTS | ||
Clear all channels except the CMD one |
||||
CLRCHN | D307 | A9 0E | LDA #$0E | Set the current secondary address in SA ($83) to $0E (#14) |
D309 | 85 83 | STA $83 | ||
CLRC1 | D30B | 20 27 D2 | JSR $D227 | JSR to FRECHN ($D227) to free the channel whose secondary address is SA |
D30E | C6 83 | DEC $83 | Decrement the value in SA ($83). If it- is not $00. branch back to CLRC1. | |
D310 | D0 F9 | BNE $D30B | ||
D312 | 60 | RTS | Terminate routine with an RTS. | |
Close all channels except the CMD one |
||||
CLDCHN | D313 | A9 0E | LDA #$0E | Set the current secondary address in SA ($83) to $0E (#14) |
D315 | 85 83 | STA $83 | ||
CLSD | D317 | A6 83 | LDX $83 | Load .X with the secondary address from SA ($83) and use it as an index to load .A with the channel number from LINTAB,X ($022B,X). Compare the channel number with $FF; if equal, no channel has been assigned so branch to CLD2. |
D319 | BD 2B 02 | LDA $022B,X | ||
D31C | C9 FF | CMP #$FF | ||
D31E | F0 14 | BEQ $D334 | ||
D320 | 29 3F | AND #$3F | AND the channel number with $3F to mask off the higher order bits and store the result in LINDX ($82) as the current channel number. | |
D322 | 85 82 | STA $82 | ||
D324 | 20 93 DF | JSR $DF93 | JSR to GETACT to get the active buffer number for this channel (returned in .A) | |
D327 | AA | TAX | Transfer the buffer number to .X and use it load .A with the last job number for this buffer from LSTJOB,X ($025B / X) . | |
D328 | BD 5B 02 | LDA $025B,X | ||
D32B | 29 01 | AND #$01 | AND the last job number with $01 and compare it with the current drive number in DRVNUM ($7F). If not equal, branch to CLD2. | |
D32D | C5 7F | CMP $7F | ||
D32F | D0 03 | BNE $D334 | ||
D331 | 20 27 D2 | JSR $D227 | JSR to FRECHN ($D227) to free this channel . | |
D334 | C6 83 | DEC $83 | Decrement the secondary address in SA ($83) and if there are more to do (not $FF yet). branch back to CLSD | |
D336 | 10 DF | BPL $D317 | ||
D338 | 60 | RTS | Terminate routine with an RTS. | |
Steal an inactive bufferScan the least recently used table and steal the first inactive buffer found. Returns the stolen buffer number in .A |
||||
STLBUF | D339 | A5 6F | LDA $6F | Save the value in TO ($6F) on the stack and zero .Y (the index to LRUTBL) . |
D33B | 48 | PHA | ||
D33C | A0 00 | LDY #$00 | ||
STL05 | D33E | B6 FA | LDX $FA,Y | Load .X (the channel index) with the value from LRUTBL, Y ($FA,Y) . |
D340 | B5 A7 | LDA $A7,X | Load .A with the buffer status for this channel from BUF0,X ($A7,X). If this buffer is active (status < 128). branch to STL10. | |
D342 | 10 04 | BPL $D348 | ||
D344 | C9 FF | CMP #$FF | Compare the status to $FF (unused). If not equal, it's inactive so branch to STL30 to steal it! | |
D346 | D0 16 | BNE $D35E | ||
STL10 | D348 | 8A | TXA | Transfer the channel number from .X to .A, clear the carry flag, add $07 (the maximum number of channels +1). and transfer the result back into .X. Note .X now points to the alternative buffer for this channel. |
D349 | 18 | CLC | ||
D34A | 69 07 | ADC #$07 | ||
D34C | AA | TAX | ||
D34D | B5 A7 | LDA $A7,X | Load .A with the buffer status for this channel from BUF0,X ($A7,X). If this buffer is active (status < 128). branch to STL3 0. | |
D34F | 10 04 | BPL $D355 | ||
D351 | C9 FF | CMP #$FF | ||
D353 | D0 09 | BNE $D35E | ||
STL20 | D355 | C8 | INY | Increment .Y and compare the new value with #$05 (the maximum number of channels +1). If there are still some channels left to check, branch to STL05 |
D356 | C0 05 | CPY #$05 | ||
D358 | 90 E4 | BCC $D33E | ||
D35A | A2 FF | LDX #$FF | No luck stealing a buffer so load .X with $FF (indicates failure) and branch to STL6 to exit. | |
D35C | D0 1C | BNE $D37A | ||
STL30 | D35E | 86 6F | STX $6F | Store the channel number (in .X) into TO ($6F) temporarily. |
D360 | 29 3F | AND #$3F | AND the buffer number in .A with $3F to mask off any higher order bits and transfer the result to .X. | |
D362 | AA | TAX | ||
STL40 | D363 | B5 00 | LDA $00,X | Check if the buffer is being used for a job currently underway by loading .A with the job queue byte for the buffer from JOBS,X ($00, X). If bit 7 is set, a job is in progress so branch back to STL40 to wait for completion. |
D365 | 30 FC | BMI $D363 | ||
D367 | C9 02 | CMP #$02 | Compare the job queue value with $02 to see if any errors occurred. If there were no errors (job queue was $01) , branch to STL50 to steal the buffer. | |
D369 | 90 08 | BCC $D373 | ||
D36B | A6 6F | LDX $6F | No luck so load .X with the value we save into TO ($6F) and compare it to $07 (the maximum number of channels+1) . | |
D36D | E0 07 | CPX #$07 | ||
D36F | 90 D7 | BCC $D348 | If .X < $07 we still need to check the alternative buffer for this channel so branch to STL10. | |
D371 | B0 E2 | BCS $D355 | If .X >= $07, we we rechecking the alternative channel so branch back to STL20 to check the next channel, | |
STL50 | D373 | A4 6F | LDY $6F | We've found an inactive buffer, now to steal it! Load .Y with the channel number from TO ($6F) and store $FF into BUF0,Y ($A7,Y) to steal it. |
D375 | A9 FF | LDA #$FF | ||
D377 | 99 A7 00 | STA $00A7,Y | ||
STL60 | D37A | 68 | PLA | Pull the original value of TO off the stack and restore it. Transfer the buffer number from .X to .A (sets the N flag if not successful) and terminate routine with an RTS. |
D37B | 85 6F | STA $6F | ||
D37D | 8A | TXA | ||
D37E | 60 | RTS | ||
Find free LINDX and allocate in LINUSE |
||||
FNDLDX | D37F | A0 00 | LDY #$00 | Load .Y with $00 and .A with $01. |
D381 | A9 01 | LDA #$01 | ||
FND10 | D383 | 2C 56 02 | BIT $0256 | Test whether the same bit is set in LINUSE ($0256) and the accumulator. If a bit is set in LINUSE, the corresponding channel is free. If the test indicates a free channel, branch to FND30. |
D386 | D0 09 | BNE $D391 | ||
D388 | C8 | INY | Increment .Y (the counter) and do an ASL on the value in the accumulator to shift the test bit one place left. If more tests are needed, branch to FND10. | |
D389 | 0A | ASL | ||
D38A | D0 F7 | BNE $D383 | ||
D38C | A9 70 | LDA #$70 | ||
D38E | 4C C8 C1 | JMP $C1C8 | No channel found so load .A with $70 to to indicate a NO CHANNEL error and JMP to CMDERR ($C1C8) . | |
FND30 | D391 | 49 FF | EOR #$FF | EOR the bit mask (in .A) with $FF to flip the bits, AND the flipped mask with LINUSE to clear the appropriate bit, and store the result back in LINUSE ($0256) . |
D393 | 2D 56 02 | AND $0256 | ||
D396 | 8D 56 02 | STA $0256 | ||
D399 | 98 | TYA | Transfer the channel number (LINDX) from .Y to .A and exit with an RTS. | |
D39A | 60 | RTS | ||
Get next byte from a channel |
||||
GBYTE | D39B | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. |
D39E | 20 00 C1 | JSR $C100 | JSR to SETLDS ($C100) to turn on the drive active light. | |
D3A1 | 20 AA D3 | JSR $D3AA | JSR to GET ($D3AA) to get one byte from any type of file. | |
D3A4 | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) and load .A with the data byte from CHNDAT,X ($023E) . | |
D3A6 | BD 3E 02 | LDA $023E,X | ||
D3A9 | 60 | RTS | Terminate routine with an RTS. | |
Get next byte from any type of file |
||||
GET | D3AA | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) JSR to TYPFIL ($D125) to determine the file type. If Z flag not set on return, this is not a relative file so branch to GET00. |
D3AC | 20 25 D1 | JSR $D125 | ||
D3AF | D0 03 | BNE $D3B4 | ||
D3B1 | 4C 20 E1 | JMP $E120 | It is a relative file so JMP to RDREL ($E120) to do this type. | |
GET00 | D3B4 | A5 83 | LDA $83 | Test if the current secondary address from SA ($83) is $0F (the CMD channel). If it is, branch to GETERC ($D414) . |
D3B6 | C9 0F | CMP #$0F | ||
D3B8 | F0 5A | BEQ $D414 | ||
D3BA | B5 F2 | LDA $F2,X | Test if the last character we sent on this channel was an EOI by checking if the channel status in CHNRDY,X ($F2,X) is $08. If the last character was NOT an EOI, branch to GET1. | |
D3BC | 29 08 | AND #$08 | ||
D3BE | D0 13 | BNE $D3D3 | ||
D3C0 | 20 25 D1 | JSR $D125 | Last character was EOI so JSR to TYPFIL ($D125) to determine the file type. | |
D3C3 | C9 07 | CMP #$07 | If the file type is NOT $07, a random access file, branch to GETO. | |
D3C5 | D0 07 | BNE $D3CE | ||
D3C7 | A9 89 | LDA #$89 | This is a direct access file so we will leave it active. Store an $89 (random access file ready) as the channel status in CHNRDY,X ($F2,X) and exit with a JMP to RNDGET ($D3DE) to get the next- character ready. | |
D3C9 | 95 F2 | STA $F2,X | ||
D3CB | 4C DE D3 | JMP $D3DE | ||
GET0 | D3CE | A9 00 | LDA #$00 | Last character sent was EOI so set the channel status as NOT READY by storing a $00 in CHNRDY,X ($F2,X). |
D3D0 | 95 F2 | STA $F2,X | ||
D3D2 | 60 | RTS | Terminate routine with an RTS. | |
GET1 | D3D3 | A5 83 | LDA $83 | Test if this is a LOAD by testing if the secondary address in SA ($83) is a $00. If it is a LOAD, branch to GET6 . |
D3D5 | F0 32 | BEQ $D409 | ||
GET2 | D3D7 | 20 25 D1 | JSR $D125 | It's not a LOAD. Maybe it's a random access file. JSR to TYPFIL ($D125) to determine the file type. If the file type is less than $04, it is NOT a random access file, so branch to SEQGET. |
D3DA | C9 04 | CMP #$04 | ||
D3DC | 90 22 | BCC $D400 | ||
RNDGET | D3DE | 20 2F D1 | JSR $D12F | It is a random access file so JSR to GETPRE ($D12F) to set up the right pointers in .X and .Y. |
D3E1 | B5 99 | LDA $99,X | Load the pointer to the data byte into .A from BUFTAB,X ($99, X). Compare this value to the pointer to the last- character pointer in LSTCHR,Y ($0244, Y) to see if we are up to the last one yet. If not, branch to RNGET1. | |
D3E3 | D9 44 02 | CMP $0244,Y | ||
D3E6 | D0 04 | BNE $D3EC | ||
D3E8 | A9 00 | LDA #$00 | We're at the last character so wrap the pointer around to the start again by storing $00 in BUFTAB,X ($99, X). | |
D3EA | 95 99 | STA $99,X | ||
RNGET1 | D3EC | F6 99 | INC $99,X | Increment BUFTAB,X ($99, X) to point to the next character. |
RNGET2 | D3EE | A1 99 | LDA ($99,X) | Load .A with the data byte from BUFTAB,X ($99, X) . |
RNGET4 | D3F0 | 99 3E 02 | STA $023E,Y | Save the data byte in CHNDAT,Y ($023E,Y) |
D3F3 | B5 99 | LDA $99,X | Load the pointer from EUFTAB,X and compare it to the value in LSTCHR,Y ($0244, Y) to see if this is the last character we're supposed to get. If NOT, branch to RNGET3 . | |
D3F5 | D9 44 02 | CMP $0244,Y | ||
D3F8 | D0 05 | BNE $D3FF | ||
D3FA | A9 81 | LDA #$81 | Since this is the last character, set the channel status in CHNRDY,Y to $00 to indicate an EOI (end of information) . | |
D3FC | 99 F2 00 | STA $00F2,Y | ||
RNGET3 | D3FF | 60 | RTS | Terminate routine with an RTS. |
SEQGET | D400 | 20 56 D1 | JSR $D156 | JSR to RDBYT ($D156) to read the next- data byte. |
GET3 | D403 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) and store the data byte in CHNDAT,X ($00F2,X) . |
D405 | 9D 3E 02 | STA $023E,X | ||
D408 | 60 | RTS | Terminate routine with an RTS. | |
GET6 | D409 | AD 54 02 | LDA $0254 | Seems to be a LOAD. Test if it is a directory listing by seeing if DIRLST ($0254) is a $00. If it is, this is not a directory listing so branch to SEQGET. |
D40C | F0 F2 | BEQ $D400 | ||
D40E | 20 67 ED | JSR $ED67 | It is a directory listing so JSR to GETDIR ($ED67) to get a byte from the directory and then JMP to GET3 . | |
D411 | 4C 03 D4 | JMP $D403 | ||
Get byte from the error channel |
||||
GETERC | D414 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to read the active buffer pointer. If the buffer number is NOT $D4, lo byte of the pointer to one byte below error buffer, branch to GE10. |
D417 | C9 D4 | CMP #$D4 | ||
D419 | D0 18 | BNE $D433 | ||
D41B | A5 95 | LDA $95 | Check if DIRBUF+1 ($95) equals $02, the hi byte of the pointer to the error buffer. If not, branch to GE10. | |
D41D | C9 02 | CMP #$02 | ||
D41F | D0 12 | BNE $D433 | ||
D421 | A9 0D | LDA #$0D | Store a $0D (#13; RETURN) in DATA ($85) and JSR to ERROFF ($C123) to turn off the error LED. | |
D423 | 85 85 | STA $85 | ||
D425 | 20 23 C1 | JSR $C123 | ||
D428 | A9 00 | LDA #$00 | Load .A with $00 and JSR to ERRTS0 ($E6C1) to transfer the error message to the error buffer. | |
D42A | 20 C1 E6 | JSR $E6C1 | ||
D42D | C6 A5 | DEC $A5 | Decrement CB+2 ($A5) so this pointer points to the start of the message, load .A with $80 (EOI out status), and branch (always!) to GE30. | |
D42F | A9 80 | LDA #$80 | ||
D431 | D0 12 | BNE $D445 | ||
GE10 | D433 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read a byte of the error message. Store the b^te in DATA ($85) and, if not $00, branch to GE20. |
D436 | 85 85 | STA $85 | ||
D438 | D0 09 | BNE $D443 | ||
GE15 | D43A | A9 D4 | LDA #$D4 | Load .A with $D4, the lo byte cf the pointer to one byte below the error buffer and JSR to SETPNT ($D4C8) to set the pointers to the error buffer. |
D43C | 20 C8 D4 | JSR $D4C8 | ||
D43F | A9 02 | LDA #$02 | Store the hi byte of the pointer to the error buffer ($02) into BUFTAB+1,X ($9A,X) . | |
D441 | 95 9A | STA $9A,X | ||
GE20 | D443 | A9 88 | LDA #$88 | Load .A with $88, the channel status byte for ready-to-talk. |
GE30 | D445 | 85 F7 | STA $F7 | Store the value in .A as the error channel status in CHNRDY+ERRCHN ($F7). |
D447 | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) and store it as the channel data byte for the error channel in CHNDAT+ERRCHN ($0243) . | |
D449 | 8D 43 02 | STA $0243 | ||
D44C | 60 | RTS | Terminate routine with an RTS. | |
Read in the next block of a file by following the track and sector linkSet an EOF (end of file) indicator if the track link (first byte) is $00. |
||||
NXTBUF | D44D | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A). Multiply the buffer number by 2 (ASL) and transfer it to .X. |
D450 | 0A | ASL | ||
D451 | AA | TAX | ||
D452 | A9 00 | LDA #$00 | Store a $00 in BUFTAB,X ($99, X) to set the buffer pointer to the first byte. | |
D454 | 95 99 | STA $99,X | ||
D456 | A1 99 | LDA ($99,X) | Check first byte (track link) in the buffer, (BUFTAB,X). If it is zero, there are no more blocks to get so branch to NXTB1. | |
D458 | F0 05 | BEQ $D45F | ||
D45A | D6 99 | DEC $99,X | Decrement the buffer pointer, BUFTAB,X ($99, X) by 1 so it is $FF and JSR to RDBYT ($D156). This forces a read of the next sector because we set the pointer to the end of the current buffer. | |
D45C | 4C 56 D1 | JMP $D156 | ||
NXTB1 | D45F | 60 | RTS | Terminate routine with an RTS. |
Direct block read |
||||
DRTRD | D460 | A9 80 | LDA #$80 | Load .A with $80, the job code for read and branch to DRT. |
D462 | D0 02 | BNE $D466 | ||
Direct block write |
||||
DRTWRT | D464 | A9 90 | LDA #$90 | Load .A with $90, the job code for write |
DRT | D466 | 05 7F | ORA $7F | OR the job code in .A with the current drive number in DRVNUM ($7F) and store the result in CMD ($024D) . |
D468 | 8D 4D 02 | STA $024D | ||
D46B | A5 F9 | LDA $F9 | Load .A with the number of the buffer to use for the job from JOBNUM ($F9) and JSR to SETH ($D6D3) to set up the header image for the job. | |
D46D | 20 D3 D6 | JSR $D6D3 | ||
D470 | A6 F9 | LDX $F9 | Load .X with the number of the buffer to use for the job from JOBNUM ($F9) and JMP to DOIT2 ($D593) to do the job. | |
D472 | 4C 93 D5 | JMP $D593 | ||
Open internal read channel: (SA=17)Use this entry point for PRG files. |
||||
OPNIRD | D475 | A9 01 | LDA #$01 | Load .A with $01 (program file type) |
Open internal read channel (.A=any type)Use this entry point for any file type. |
||||
OPNTYP | D477 | 8D 4A 02 | STA $024A | Store file type (.A) into TYPE ($024A) |
D47A | A9 11 | LDA #$11 | Store $11 (#17) as the current secondary address in SA ($83) . | |
D47C | 85 83 | STA $83 | ||
D47E | 20 46 DC | JSR $DC46 | JSR to OPNRCH ($DC46) to open a read channel . | |
D481 | A9 02 | LDA #$02 | Set .A to $02 and JMP to SETPNT ($D4C8) to set the buffer pointer to point past the track and sector link. | |
D483 | 4C C8 D4 | JMP $D4C8 | ||
Open internal write channel (SA=18) |
||||
OPNIWR | D486 | A9 12 | LDA #$12 | Store $12 (#18) as the current secondary address in SA ($83) . |
D488 | 85 83 | STA $83 | ||
D48A | 4C DA DC | JMP $DCDA | JMP to OPNWCH ($DCDA) to open the write channel . | |
Allocate the next directory block |
||||
NXDRBK | D48D | 20 3B DE | JSR $DE3B | JSR to CURBLK ($DE3B) set the TRACK ($80) and SECTOR ($81) values from the current header. |
D490 | A9 01 | LDA #$01 | Set TEMP ($6F) to $01 and save the current value of SECINC ($69). the sector increment used for sequential files, on the stack. | |
D492 | 85 6F | STA $6F | ||
D494 | A5 69 | LDA $69 | ||
D496 | 48 | PHA | ||
D497 | A9 03 | LDA #$03 | Set the sector increment, SECINC ($69) to $03, the increment used for the directory track. | |
D499 | 85 69 | STA $69 | ||
D49B | 20 2D F1 | JSR $F12D | JSF to NXTDS ($F12D) to determine the next available track and sector. | |
D49E | 68 | PLA | Restore the original sector increment in SECINC ($69) from the stack. | |
D49F | 85 69 | STA $69 | ||
D4A1 | A9 00 | LDA #$00 | Set .A to $00 and JSR to SETPNT ($D4C8) to set the pointer to the first byte in the active buffer (track byte) . | |
D4A3 | 20 C8 D4 | JSR $D4C8 | ||
D4A6 | A5 80 | LDA $80 | Load .A with the next track from TRACK ($80) and JSR to PUTBYT ($CFF1) to store the track link in the buffer. | |
D4A8 | 20 F1 CF | JSR $CFF1 | ||
D4AB | A5 81 | LDA $81 | Load .A with the next sector from SECTOR ($81) and JSR to PUTBYT ($CFF1) to store the sector link in the buffer. | |
D4AD | 20 F1 CF | JSR $CFF1 | ||
D4B0 | 20 C7 D0 | JSR $D0C7 | JSR to WRTBUF ($D0C7) to write the buffer out to disk. | |
D4B3 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait until the write job is complete. | |
D4B6 | A9 00 | LDA #$00 | Set .A to $00 and JSR to SETPNT ($D4C8) to set the pointer to the first byte in the active buffer (track byte) . | |
D4B8 | 20 C8 D4 | JSR $D4C8 | ||
NXDB1 | D4BB | 20 F1 CF | JSR $CFF1 | Loop to zero the entire buffer. |
D4BE | D0 FB | BNE $D4BB | ||
D4C0 | 20 F1 CF | JSR $CFF1 | JSR to PUTBYT ($CFF1) to store $00 as the next track link. | |
D4C3 | A9 FF | LDA #$FF | Load .A with $FF and JMP to PUTBYT ($CFF1) to store $FF as the sector link. | |
D4C5 | 4C F1 CF | JMP $CFF1 | ||
Set up pointer into active data bufferOn entry: .A contains new pointer value |
||||
SETPNT | D4C8 | 85 6F | STA $6F | Save the new pointer (in .A) into TEMP ($6F) and JSR to GETACT ($DF93) to find the active buffer number (in .A) . |
D4CA | 20 93 DF | JSR $DF93 | ||
D4CD | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer the result into .X. | |
D4CE | AA | TAX | ||
D4CF | B5 9A | LDA $9A,X | Move the high byte of the buffer pointer from BUFTAB+1,X ($9A,X) to DIRBUF+1 ($95) | |
D4D1 | 85 95 | STA $95 | ||
D4D3 | A5 6F | LDA $6F | Load the new buffer pointer value from TEMP ($6F) into .A. Store this new value into BUFTAB,X ($99, X) and DIRBUF ($94). | |
D4D5 | 95 99 | STA $99,X | ||
D4D7 | 85 94 | STA $94 | ||
D4D9 | 60 | RTS | Terminate routine with an RTS. | |
Free both internal channels: (SA=17&18) |
||||
FREICH | D4DA | A9 11 | LDA #$11 | Set SA ($83) to $11 (#17) the internal read channel and JSR to FRECHN ($D227) to free the internal read channel. |
D4DC | 85 83 | STA $83 | ||
D4DE | 20 27 D2 | JSR $D227 | ||
D4E1 | A9 12 | LDA #$12 | Set SA ($83) to $12 (#18) the internal write channel and JMP to FRECHN ($D227) to free the internal write channel. | |
D4E3 | 85 83 | STA $83 | ||
D4E5 | 4C 27 D2 | JMP $D227 | ||
Get the active buffer pointer |
||||
GETPNT | D4E8 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A) . |
SETDIR | D4EB | 0A | ASL | Multiply the buffer number by two (ASL) and transfer the result into .X. |
D4EC | AA | TAX | ||
D4ED | B5 9A | LDA $9A,X | Move the hi byte of the buffer pointer from BUFTAB+1,X ($9A,X) into the hi byte of the directory buffer pointer DIRBUF + 1 ($95) . | |
D4EF | 85 95 | STA $95 | ||
D4F1 | B5 99 | LDA $99,X | Move the lo byte of the buffer pointer from BUFTAB,X ($99, X) into the lo byte of the directory buffer pointer DIRBUF ($94). (.A = lo byte of the pointer) | |
D4F3 | 85 94 | STA $94 | ||
D4F5 | 60 | RTS | Terminate routine with an RTS. | |
Direct read of a byte: (.A = position)On entry: .A = position of byte in buffer On exit: .A = data byte desired |
||||
DRDBYT | D4F6 | 85 71 | STA $71 | Store lo byte of pointer to desired byte (in .A) into TEMP+2 ($71). |
D4F8 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A) . | |
D4FB | AA | TAX | Transfer buffer number into .X and load .A with the hi byte of the active buffer pointer from BUFIND,X ($FEE0,X). Store this value into TEMP+3 ($72). This creates a pointer to the byte in $71/72. | |
D4FC | BD E0 FE | LDA $FEE0,X | ||
D4FF | 85 72 | STA $72 | ||
D501 | A0 00 | LDY #$00 | Zero .Y and load .A with the desired byte from (TEMP+2), Y; ($71), Y. | |
D503 | B1 71 | LDA ($71),Y | ||
D505 | 60 | RTS | Terminate routine with an RTS. | |
Set up job using last job's drive
|
||||
SETLJB | D506 | BD 5B 02 | LDA $025B,X | Load .A with previous job number from LSTJOB,X ($025B,X), AND the job number with $01 to leave just the drive number bits, and OR the result with the new job code on CMD ($024D). The resulting new job code is in .A. |
D509 | 29 01 | AND #$01 | ||
D50B | 0D 4D 02 | ORA $024D | ||
Set up new job
|
||||
SETJOB | D50E | 48 | PHA | Save new job code on the stack and store the number of the buffer to use (.X) in JOBNUM ($F9) . |
D50F | 86 F9 | STX $F9 | ||
D511 | 8A | TXA | Transfer the buffer number from .X to .A, multiply it by 2 (ASL) and transfer it back into .X. | |
D512 | 0A | ASL | ||
D513 | AA | TAX | ||
D514 | B5 07 | LDA $07,X | Move the desired sector from HDRS+1,X ($07, X) into CMD ($024D). | |
D516 | 8D 4D 02 | STA $024D | ||
D519 | B5 06 | LDA $06,X | Load .A with the desired track from HDRS,X ($06, X). If it is $00, branch to TSERR ($D54A) . | |
D51B | F0 2D | BEQ $D54A | ||
D51D | CD D7 FE | CMP $FED7 | Compare the desired track (in .A) with the maximum track number from MAXTRK ($FED7). If it is too large, branch to TSERR ($D54A) . | |
D520 | B0 28 | BCS $D54A | ||
D522 | AA | TAX | Transfer the desired track number from .A to .X. | |
D523 | 68 | PLA | Pull the job code off the stack and immediately push it back onto the stack. | |
D524 | 48 | PHA | ||
D525 | 29 F0 | AND #$F0 | AND the job code in .A with $F0 to mask off the drive bits and compare it to $90 (the job code for a write). If this is not a write job, branch to SJB1. | |
D527 | C9 90 | CMP #$90 | ||
D529 | D0 4F | BNE $D57A | ||
D52B | 68 | PLA | Pull the job code off the stack and immediately push it back onto the stack. | |
D52C | 48 | PHA | ||
D52D | 4A | LSR | Do an LSR on the job code in .A to find the drive to use. If it is drive 1, branch to SJB2. | |
D52E | B0 05 | BCS $D535 | ||
D530 | AD 01 01 | LDA $0101 | Use drive so load DOS version from DSKVER ($0101) and branch to S JB3 . | |
D533 | 90 03 | BCC $D538 | ||
SJB2 | D535 | AD 02 01 | LDA $0102 | Use drive 1 so load DOS version from DSKVER+1 ($0102) . |
SJB3 | D538 | F0 05 | BEQ $D53F | If DOS version is $00 (no number). it is OK, so branch to SJB4. |
|
||||
D53A | CD D5 FE | CMP $FED5 | Compare the DOS version number with the 1541 DOS version number ($65) from VERNUM ($FED5). If the version numbers do not match, branch to VNERR ($D572). | |
D53D | D0 33 | BNE $D572 | ||
SJB4 | D53F | 8A | TXA | Transfer the desired track number from .X to .A and JSR to MAXSEX ($F24B) to calculate the maximum sector number+1 for this track (returned in .A). Compare this value with the desired sector number in CMD. If the desired sector number is legal, branch to SJB1 . |
D540 | 20 4B F2 | JSR $F24B | ||
D543 | CD 4D 02 | CMP $024D | ||
D546 | F0 02 | BEQ $D54A | ||
D548 | B0 30 | BCS $D57A | ||
TSERR | D54A | 20 52 D5 | JSR $D552 | Track and/or sector number is illegal so JSR to HED2TS ($D552) to store the values in TRACK ($80) and SECTOR ($81) . |
TSER1 | D54D | A9 66 | LDA #$66 | Load .A with $66 to indicate a bad track and sector and JMP to CMDER2 ($E645). |
D54F | 4C 45 E6 | JMP $E645 | ||
HED2TS | D552 | A5 F9 | LDA $F9 | Set desired track and sector values: Load .A with the number of the buffer to use for this job from JOBNUM ($F9). Multiply the buffer number by 2 (ASL) and transfer it to .X. |
D554 | 0A | ASL | ||
D555 | AA | TAX | ||
D556 | B5 06 | LDA $06,X | Move the desired track number from HDRS,X ($06, X) to TRACK ($80). | |
D558 | 85 80 | STA $80 | ||
D55A | B5 07 | LDA $07,X | Move the desired sector number from HDRS+1,X ($07, X) to SECTOR ($81). | |
D55C | 85 81 | STA $81 | ||
D55E | 60 | RTS | Terminate routine with an RTS. | |
Check for bad track and sector values |
||||
TSCHK | D55F | A5 80 | LDA $80 | Load .A from TRACK ($80). If the track is $00, branch back to TSER1 ($D54D). |
D561 | F0 EA | BEQ $D54D | ||
D563 | CD D7 FE | CMP $FED7 | Compare the track to the maximum track number allowed, MAXTRK ($FED7). If too large, branch back to TSER1. | |
D566 | B0 E5 | BCS $D54D | ||
D568 | 20 4B F2 | JSR $F24B | JSR to MAXSEC ($F24B) to calculate the maximum sector number allowed on this track. If too large, branch to TSER1. | |
D56B | C5 81 | CMP $81 | ||
D56D | F0 DE | BEQ $D54D | ||
D56F | 90 DC | BCC $D54D | ||
D571 | 60 | RTS | Terminate routine with an RTS. | |
Bad DOS version number |
||||
VNERR | D572 | 20 52 D5 | JSR $D552 | JSR to HED2TS ($D552) to store the values in TRACK ($80) and SECTOR ($81). |
D575 | A9 73 | LDA #$73 | Load .A with $73 to indicate a bad DOS version number and JMP to CMDER2 ($E645) to | |
D577 | 4C 45 E6 | JMP $E645 | ||
Conclude job set up |
||||
SJB1 | D57A | A6 F9 | LDX $F9 | Load .X with the number of the buffer use for the job from JOBNUM ($F9) . |
D57C | 68 | PLA | Pull the job code off the stack. | |
D57D | 8D 4D 02 | STA $024D | Store the job code as the current command in CMD ($024D). in the job gueue at JOBS,X ($00, X) to activate the disk controller, and in LSTJOB,X. | |
D580 | 95 00 | STA $00,X | ||
D582 | 9D 5B 02 | STA $025B,X | ||
D585 | 60 | RTS | Terminate routine with an RTS, | |
Do a read job; return when done OK: |
||||
DOREAD | D586 | A9 80 | LDA #$80 | Load .A with $80. the read job code and branch to DOJOB. |
D588 | D0 02 | BNE $D58C | ||
DOWRIT | D58A | A9 90 | LDA #$90 | Do a write job; return when done OK: Load .A with $90. the write job cede. |
DOJOB | D58C | 05 7F | ORA $7F | OR the job code with the current drive number in DF:VNUM ($7F) . |
D58E | A6 F9 | LDX $F9 | Load .X with the number of the buffer to use for the job from JOBNUM ($F9) . | |
DOIT | D590 | 8D 4D 02 | STA $024D | Store complete job code in CMD ($024D) . |
DOIT2 | D593 | AD 4D 02 | LDA $024D | Lead .A with job code from CMD ($024D) . |
D596 | 20 0E D5 | JSR $D50E | JSR to SETJOB ($D50E) to start job. | |
Wait until job is completed |
||||
WATJOB | D599 | 20 A6 D5 | JSR $D5A6 | JSR to TSTJOB ($D5A6) to check if job is done yet (error code returned in .A) |
D59C | B0 FB | BCS $D599 | If job not done yet, branch to WATJOB. | |
D59E | 48 | PHA | Save error cede on the stack. | |
D59F | A9 00 | LDA #$00 | Set job completed flag, JOBRTN ($0298), to $00. | |
D5A1 | 8D 98 02 | STA $0298 | ||
D5A4 | 68 | PLA | Recover error code from stack (in .A). | |
D5A5 | 60 | RTS | Terminate routine with an RTS. | |
Test if job done yet |
||||
TSTJOB | D5A6 | B5 00 | LDA $00,X | If not done, return. If done OK, then return. If not OK, redo the job. Load .A with value from the job queue, JOBS,X ($00, X) . |
D5A8 | 30 1A | BMI $D5C4 | If .A > 127, job not done yet so branch to NOTYET to exit with carry flag set. | |
D5AA | C9 02 | CMP #$02 | If .A < 2, job was completed with no errors so branch to OK to exit with the carry flag clear. | |
D5AC | 90 14 | BCC $D5C2 | ||
D5AE | C9 08 | CMP #$08 | Compare the error code to $08. If it is $08, a fatal write protect error has occured so branch to TJ10 and abort. | |
D5B0 | F0 08 | BEQ $D5BA | ||
D5B2 | C9 0B | CMP #$0B | Compare the error code to $0B. If it is $0B, a fatal ID mismatch error has occured so branch to TJ10 and abort. | |
D5B4 | F0 04 | BEQ $D5BA | ||
D5B6 | C9 0F | CMP #$0F | Compare the error code to $0F. If it is NOT $0F, a non-fatal error has occured so branch to RECOV and try again. NOTE: an error code of $0F means a fatal drive-not-available error has occured. | |
D5B8 | D0 0C | BNE $D5C6 | ||
TJ10 | D5BA | 2C 98 02 | BIT $0298 | Test bit 7 of the job return flag, JOBRTN ($0298). If it is set, the disk has been initialized and this is the first attempt to carry out the job, so branch to OK to return with the carry flag clear. |
D5BD | 30 03 | BMI $D5C2 | ||
D5BF | 4C 3F D6 | JMP $D63F | JMP to QUIT2 ($D63F) to try to recover. | |
OK | D5C2 | 18 | CLC | Clear the carry flag and terminate the routine with an RTS. |
D5C3 | 60 | RTS | ||
NOTYET | D5C4 | 38 | SEC | Set the carry flag and terminate the routine with an RTS. |
D5C5 | 60 | RTS | ||
RECOV | D5C6 | 98 | TYA | Save .Y value and the current drive number from DRVNUM ($7F) on the stack. |
D5C7 | 48 | PHA | ||
D5C8 | A5 7F | LDA $7F | ||
D5CA | 48 | PHA | ||
D5CB | BD 5B 02 | LDA $025B,X | Load the job code for the last job from LSTJOB,X ($025B,X). AND it with $01 to mask off the non-drive bits, and store the result as the current drive number in DRVNUM ($7F) . | |
D5CE | 29 01 | AND #$01 | ||
D5D0 | 85 7F | STA $7F | ||
D5D2 | A8 | TAY | Transfer the drive number from .A to .Y and move the LED error mask from LEDMSK,Y ($FECA,Y) to ERLED ($026D) | |
D5D3 | B9 CA FE | LDA $FECA,Y | ||
D5D6 | 8D 6D 02 | STA $026D | ||
D5D9 | 20 A6 D6 | JSR $D6A6 | JSR to DOREC ($D6A6) to do last job recovery. On return, if the error code (in .A) is $01, it worked so branch to REC01. | |
D5DC | C9 02 | CMP #$02 | ||
D5DE | B0 03 | BCS $D5E3 | ||
D5E0 | 4C 6D D6 | JMP $D66D | Retry didn't work, JMP to REC95 ($D66D) | |
REC01 | D5E3 | BD 5B 02 | LDA $025B,X | Load .A with the original job code from LSTJOB,X ($025B,X). AND it with $F0 to mask off the drive number bits, and save it on the stack. |
D5E6 | 29 F0 | AND #$F0 | ||
D5E8 | 48 | PHA | ||
D5E9 | C9 90 | CMP #$90 | Check if the job code was $90 (a write job). If not, branch to RECO. | |
D5EB | D0 07 | BNE $D5F4 | ||
D5ED | A5 7F | LDA $7F | This is a write job. OR the current drive number from DRVNUM ($7F) with $B8 (the job code for a sector seek) and store the result in LSTJOB,X ($025B,X) . This replaces the original write job with a seek job during recovery. | |
D5EF | 09 B8 | ORA #$B8 | ||
D5F1 | 9D 5B 02 | STA $025B,X | ||
REC0 | D5F4 | 24 6A | BIT $6A | See if the head is on track by checking bit 6 of REVCNT (6A). If this bit is set, the head is on track so branch to REC5. Head not on track so zero the offset table pointer, EPTR ($0299) and the total offset TOFF ($029A) . |
D5F6 | 70 39 | BVS $D631 | ||
D5F8 | A9 00 | LDA #$00 | ||
D5FA | 8D 99 02 | STA $0299 | ||
D5FD | 8D 9A 02 | STA $029A | ||
REC1 | D600 | AC 99 02 | LDY $0299 | Load .Y with the offset table pointer EPTR ($0299) and .A with the total offset TOFF ($029A) . |
D603 | AD 9A 02 | LDA $029A | ||
D606 | 38 | SEC | Set the carry flag and subtract the offset OFFSET, Y ($FEDB) from the total offset in .A. Store the result as the new total offset in TOFF ($029A). | |
D607 | F9 DB FE | SBC $FEDB,Y | ||
D60A | 8D 9A 02 | STA $029A | ||
D60D | B9 DB FE | LDA $FEDB,Y | Load .A with the head offset from OFFSET, Y and JSR to HEDOFF ($D676) to move the head so it is on track. | |
D610 | 20 76 D6 | JSR $D676 | ||
D613 | EE 99 02 | INC $0299 | Increment the offset table pointer and JSR to DOREC ($D6A6) to attempt to recover. On return, if the error code in .A < $02, the recovery worked so branch to REC3 . | |
D616 | 20 A6 D6 | JSR $D6A6 | ||
D619 | C9 02 | CMP #$02 | ||
D61B | 90 08 | BCC $D625 | ||
D61D | AC 99 02 | LDY $0299 | That try at recovery did not work so increment the offset table pointer by 1 and load .A with the offset from OFFSET, Y ($FEDB,Y). If the value loaded is not $00, branch to REC1 to try again. | |
D620 | B9 DB FE | LDA $FEDB,Y | ||
D623 | D0 DB | BNE $D600 | ||
REC3 | D625 | AD 9A 02 | LDA $029A | One more try on the offset. Load .A with the total offset from TOFF ($029A) and JSR to HEDOFF ($D676). If no error on return, branch to REC9. |
D628 | 20 76 D6 | JSR $D676 | ||
D62B | B5 00 | LDA $00,X | ||
D62D | C9 02 | CMP #$02 | ||
D62F | 90 2B | BCC $D65C | ||
REC5 | D631 | 24 6A | BIT $6A | Check bit 7 of the error recover count REVCNT ($6A). If this bit is clear, branch to REC7 to do a bump to track 1. |
D633 | 10 0F | BPL $D644 | ||
QUIT | D635 | 68 | PLA | Pull the original job code off the stack. If it is NOT $90 (a write job) branch to QUIT2. |
D636 | C9 90 | CMP #$90 | ||
D638 | D0 05 | BNE $D63F | ||
D63A | 05 7F | ORA $7F | For write jobs only, OR the job code in .A with the drive number from DRVNUM and put the result in LSTJOB,X ($025B,X) to restore the original value. | |
D63C | 9D 5B 02 | STA $025B,X | ||
QUIT2 | D63F | B5 00 | LDA $00,X | Load .A with the error code from JOBS,X ($00,X) and abort with a JSR to ERROR ($E60A) . |
D641 | 20 0A E6 | JSR $E60A | ||
REC7 | D644 | 68 | PLA | Pull the job code off the stack (in .A). |
REC5 | D645 | 2C 98 02 | BIT $0298 | Check bit 7 of the job return flag JOBRTN ($0298). If this bit is set, branch to REC95 to exit with job error. Push the job code back onto the stack. |
D648 | 30 23 | BMI $D66D | ||
D64A | 48 | PHA | ||
D64B | A9 C0 | LDA #$C0 | Do a bump to track 1 by loading .A with $C0 (BUMP job code). ORing it. with the current drive number from DRVNUM ($7F) , and storing the result in the job queue at JOBS,X ($00, X) . | |
D64D | 05 7F | ORA $7F | ||
D64F | 95 00 | STA $00,X | ||
REC8 | D651 | B5 00 | LDA $00,X | Wait for current job to be completed. |
D653 | 30 FC | BMI $D651 | ||
D655 | 20 A6 D6 | JSR $D6A6 | JSR to DOREC ($D6A6) to try one more time. On return, if the error code (.A) is not $01 (no error). give up in disgust and branch to QUIT. | |
D658 | C9 02 | CMP #$02 | ||
D65A | B0 D9 | BCS $D635 | ||
REC9 | D65C | 68 | PLA | Pull the original job code off the stack and compare it to $90 (the job code for a write job). If this isn't a write job, branch to REC9 5. |
D65D | C9 90 | CMP #$90 | ||
D65F | D0 0C | BNE $D66D | ||
D661 | 05 7F | ORA $7F | OR the job code (in .A) with the drive number from DRVNUM ($7F) and store the value in LSTJOB,X. | |
D663 | 9D 5B 02 | STA $025B,X | ||
D666 | 20 A6 D6 | JSR $D6A6 | JSR to DOREC ($D6A6) to try one last time. On return, if the error code (.A) is not $01 (no error). give up in disgust and branch to QUIT2. | |
D669 | C9 02 | CMP #$02 | ||
D66B | B0 D2 | BCS $D63F | ||
REC95 | D66D | 68 | PLA | Pull the original drive number off the stack and store it in DRVNUM ($7F) . |
D66E | 85 7F | STA $7F | ||
D670 | 68 | PLA | Pull the original .Y value off the stack and restore .Y. | |
D671 | A8 | TAY | ||
D672 | B5 00 | LDA $00,X | Load .A with the error code from JOBS,X ($00, X). clear the carry flag, and exit with an RTS . | |
D674 | 18 | CLC | ||
D675 | 60 | RTS | ||
Adjust head offsetOn entry: .A = OFFSET |
||||
HEDOFF | D676 | C9 00 | CMP #$00 | If .A=0, no offset required so branch to HOF3. |
D678 | F0 18 | BEQ $D692 | ||
D67A | 30 0C | BMI $D688 | If .A > 127, head needs to be stepped inward so branch to HOF2. | |
HOF1 | D67C | A0 01 | LDY #$01 | We want to move head outward 1 track so: load .Y with $01 and JSR to MOVHED ($D693) to move the head. |
D67E | 20 93 D6 | JSR $D693 | ||
D681 | 38 | SEC | On return, set the carry flag and subtract $01 from the value in .A. If the result is not $00, the head has not- finished so branch back to HOF1. | |
D682 | E9 01 | SBC #$01 | ||
D684 | D0 F6 | BNE $D67C | ||
D686 | F0 0A | BEQ $D692 | If the head is finished moving, branch to HOF3. | |
HOF2 | D688 | A0 FF | LDY #$FF | We want to move head inward 1 track so: load .Y with $FF and JSR to MOVHED ($D693) to move the head. |
D68A | 20 93 D6 | JSR $D693 | ||
D68D | 18 | CLC | On return, clear the carry flag and add $01 to the value in .A. If the result is not $00, the head has not finished so branch back to HOF2. | |
D68E | 69 01 | ADC #$01 | ||
D690 | D0 F6 | BNE $D688 | ||
HOF3 | D692 | 60 | RTS | Terminate routine with an RTS. |
Step head inward or outward 1 track |
||||
MCVHED | D693 | 48 | PHA | Save the value in .A onto the stack. |
D694 | 98 | TYA | Transfer the number of steps to move (phase) from .Y into .A. | |
D695 | A4 7F | LDY $7F | Load. Y with the current drive number from DRVNUM ($7F) . | |
D697 | 99 FE 02 | STA $02FE,Y | Store the phase into PHASE, Y ($02FE,Y). | |
MH10 | D69A | D9 FE 02 | CMP $02FE,Y | Compare the phase in .A with the value in PHASE, Y ($02FE,Y). If they are equal, the controller has not yet moved the head so branch back to MH10. |
D69D | F0 FB | BEQ $D69A | ||
D69F | A9 00 | LDA #$00 | Store $00 in PHASE, Y ($02FE,Y) so head won't move any more. | |
D6A1 | 99 FE 02 | STA $02FE,Y | ||
D6A4 | 68 | PLA | Pull original value of .A off the stack. | |
D6A5 | 60 | RTS | Terminate routine with an RTS. | |
DOREC | D6A6 | A5 6A | LDA $6A | Load .A with the retry counter, REVCNT ($6A). AND it with $3F to mask off the high order bits, and transfer the result into .Y. |
D6A8 | 29 3F | AND #$3F | ||
D6AA | A8 | TAY | ||
DOREC1 | D6AB | AD 6D 02 | LDA $026D | Load .A with the error LED mask from ERLED ($026D). EOR it with the disk controller port B, DSKCNT ($1C00) and store it back in DSKCNT ($1C00) to turn the drive light OFF. |
D6AE | 4D 00 1C | EOR $1C00 | ||
D6B1 | 8D 00 1C | STA $1C00 | ||
D6B4 | BD 5B 02 | LDA $025B,X | Restart the last job by moving the job code from LSTJOB,X ($025B,X) to the job queue at JOBS,X ($00, X). | |
D6B7 | 95 00 | STA $00,X | ||
DOREC2 | D6B9 | B5 00 | LDA $00,X | Loop to wait until the value in the job queue at JOBS,X ($00, X) is less than 127 (indicates job has been completed). Test to see if the error code returned is $01 (successful). If everything was OK, branch to DOREC3. |
D6BB | 30 FC | BMI $D6B9 | ||
D6BD | C9 02 | CMP #$02 | ||
D6BF | 90 03 | BCC $D6C4 | ||
D6C1 | 88 | DEY | It didn't work. Decrement the error counter in .Y and, if .Y has not counted down to $00 yet, branch to DOREC1 and keep trying. | |
D6C2 | D0 E7 | BNE $D6AB | ||
DOREC3 | D6C4 | 48 | PHA | Save the error code onto the stack. |
D6C5 | AD 6D 02 | LDA $026D | Load .A with the error LED mask from ERLED ($026D). OR it with the disk controller port B, DSKCNT ($1C00) and store it back in DSKCNT ($1C00) to turn the drive light back ON. | |
D6C8 | 0D 00 1C | ORA $1C00 | ||
D6CB | 8D 00 1C | STA $1C00 | ||
D6CE | 68 | PLA | Pull the error code back off the stack. | |
D6CF | 60 | RTS | Terminate routine with an RTS. | |
Set up the header for the active buffer |
||||
SETHDR | D6D0 | 20 93 DF | JSR $DF93 | Uses values in TRACK, SECTOR, & DSKID. JSR to GETACT ($DF93) to get the number of the active buffer (returned in .A) . |
D6D3 | 0A | ASL | Multiply the number of the active buffer (in .A) by 2 (ASL) and transfer the result into .Y. | |
D6D4 | A8 | TAY | ||
D6D5 | A5 80 | LDA $80 | Move the track number from TRACK ($80) to HDRS,Y ($0006, Y) . | |
D6D7 | 99 06 00 | STA $0006,Y | ||
D6DA | A5 81 | LDA $81 | Move the sector number from SECTOR ($81) to HDRS+1,Y ($0007, Y) . | |
D6DC | 99 07 00 | STA $0007,Y | ||
D6DF | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F). multiply it by 2 (ASL) and transfer the result to .X.
| |
D6E1 | 0A | ASL | ||
D6E2 | AA | TAX | ||
D6E3 | 60 | RTS | Terminate routine with an RTS. | |
Add new filename to the directory |
||||
ADDFIL | D6E4 | A5 83 | LDA $83 | Save the following variables onto the stack: SA ($83), LINDX ($82), SECTOR ($81). and TRACK ($80) . |
D6E6 | 48 | PHA | ||
D6E7 | A5 82 | LDA $82 | ||
D6E9 | 48 | PHA | ||
D6EA | A5 81 | LDA $81 | ||
D6EC | 48 | PHA | ||
D6ED | A5 80 | LDA $80 | ||
D6EF | 48 | PHA | ||
D6F0 | A9 11 | LDA #$11 | Set the current secondary address, SA ($83) to $11 (#17), the internal read channel . | |
D6F2 | 85 83 | STA $83 | ||
D6F4 | 20 3B DE | JSR $DE3B | JSR to CURBLK ($DE3B) to find a read channel and set TRACK ($80) and SECTOR ($81) from the most recently read header | |
D6F7 | AD 4A 02 | LDA $024A | Save the file type, TYPE ($024A) of the file to be added onto the stack. | |
D6FA | 48 | PHA | ||
D6FB | A5 E2 | LDA $E2 | Load .A with the drive number for the new file, and it with $01, and store the result as the current drive, DRVNUM($7F) | |
D6FD | 29 01 | AND #$01 | ||
D6FF | 85 7F | STA $7F | ||
D701 | A6 F9 | LDX $F9 | Load .X with the last job number frcm JOBNUM ($F9) . | |
D703 | 5D 5B 02 | EOR $025B,X | ||
D706 | 4A | LSR | EOR the drive number in .A with the last job code from LSTJOB,X ($025B,X) , divide the result by 2 (LSR). and check if the carry flag is clear. If it is, the new file uses the same drive as the last job so there is no need to change the drive and we can branch to AF08. | |
D707 | 90 0C | BCC $D715 | ||
D709 | A2 01 | LDX #$01 | Store $01 in DELIND ($0292) to indicate that we are searching for a deleted entry and JSR to SRCHST ($C5AC). On return, if .A=0, all directory sectors are full so branch to AF15 to start a new sector. If .AO0, we have found a spot to put the new entry so branch to AF20. | |
D70B | 8E 92 02 | STX $0292 | ||
D70E | 20 AC C5 | JSR $C5AC | ||
D711 | F0 1D | BEQ $D730 | ||
D713 | D0 28 | BNE $D73D | ||
AF08 | D715 | AD 91 02 | LDA $0291 | Since we have used this drive before, some of the directory information is in memory. Check if DELSEC ($0291) is $00. If it is, we didn't locate a deleted entry the last time we read in the directory so branch to AF10. |
D718 | F0 0C | BEQ $D726 | ||
D71A | C5 81 | CMP $81 | Since DELSEC is not $00, it is the number of the sector containing the first available directory entry. See if this sector is currently in memory by comparing this sector number with the one in SECTOR ($81). If they are equal, the sector is in memory so branch to AF20. | |
D71C | F0 1F | BEQ $D73D | ||
D71E | 85 81 | STA $81 | Since the desired sector is not in memory, set SECTOR ($81) to the desired sector number and JSR to DRTRD ($D460) to read in the sector. Now branch to AF20. | |
D720 | 20 60 D4 | JSR $D460 | ||
D723 | 4C 3D D7 | JMP $D73D | ||
AF10 | D726 | A9 01 | LDA #$01 | Store $01 in DELIND ($0292) to indicate that we are looking for a deleted entry and JSR to SEARCH ($C617) to find the first deleted or empty directory entry. |
D728 | 8D 92 02 | STA $0292 | ||
D72B | 20 17 C6 | JSR $C617 | ||
D72E | D0 0D | BNE $D73D | On return, if .A is not equal to $00, a deleted or empty entry was found so branch to AF20. | |
AF15 | D730 | 20 8D D4 | JSR $D48D | No empty entries so we have to start a new sector so JSR to NXDRBK ($D48D) to find us the next available sector. |
D733 | A5 81 | LDA $81 | Move the new sector number from SECTOR ($81) to DELSEC ($0291) and set DELIND ($0292) to $02. | |
D735 | 8D 91 02 | STA $0291 | ||
D738 | A9 02 | LDA #$02 | ||
D73A | 8D 92 02 | STA $0292 | ||
AF20 | D73D | AD 92 02 | LDA $0292 | Load .A with the pointer that points to first character in the directory entry, DELIND($0292). and JSR to SETPNT ( $D4C8 ) to set the pointers to this entry. |
D740 | 20 C8 D4 | JSR $D4C8 | ||
D743 | 68 | PLA | Pull the file type off the stack and store it back in TYPE ($024A) . | |
D744 | 8D 4A 02 | STA $024A | ||
D747 | C9 04 | CMP #$04 | Compare the file type to $04 (REL type) . If this is not a relative file, branch to AF25. | |
D749 | D0 02 | BNE $D74D | ||
D74B | 09 80 | ORA #$80 | Since it is a REL file, OR the file type (in .A) with $80 to set bit 7. | |
AF25 | D74D | 20 F1 CF | JSR $CFF1 | JSR to PUTBYT ($CFF1) to store the file type (in .A) into the buffer. |
D750 | 68 | PLA | Pull the file's track link off the stack, store it in FILTRK ($0280). and JSR to PUTBYT ($CFF1) to store the track link in the buffer. | |
D751 | 8D 80 02 | STA $0280 | ||
D754 | 20 F1 CF | JSR $CFF1 | ||
D757 | 68 | PLA | Pull the file's sector link off the stack, store it in FILSEC ($0285). and JSR to PUT3YT ($CFF1) to store the sector link in the buffer. | |
D758 | 8D 85 02 | STA $0285 | ||
D75B | 20 F1 CF | JSR $CFF1 | ||
D75E | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (in .A) and transfer the value to .Y | |
D761 | A8 | TAY | ||
D762 | AD 7A 02 | LDA $027A | Load .X with the file table pointer from FILTAB ($027A) . | |
D765 | AA | TAX | ||
D766 | A9 10 | LDA #$10 | Load .A with $10 (#16) and JSR to TRNAME ($C66E) to transfer the file name to the buffer. | |
D768 | 20 6E C6 | JSR $C66E | ||
D76B | A0 10 | LDY #$10 | ||
D76D | A9 00 | LDA #$00 | Loop to fill directory entry with $00' s from (DIRBUF),16 to (DIRBUF),27. | |
D76F | 91 94 | STA ($94),Y | ||
D771 | C8 | INY | ||
D772 | C0 1B | CPY #$1B | ||
D774 | 90 F9 | BCC $D76F | ||
D776 | AD 4A 02 | LDA $024A | Check the value in TYPE ($024A) to see if this is a relative file. If not, branch to AF50. | |
D779 | C9 04 | CMP #$04 | ||
D77B | D0 13 | BNE $D790 | ||
D77D | A0 10 | LDY #$10 | For REL files only: Load .Y with $10. | |
D77F | AD 59 02 | LDA $0259 | Move the side-sector track number from TRKSS ($0259) to (DIRBUF),Y. Increment Y | |
D782 | 91 94 | STA ($94),Y | ||
D784 | C8 | INY | ||
D785 | AD 5A 02 | LDA $025A | Move the side-sector sector number from SECSS ($025A) to (DIRBUF) ,Y. Increment Y | |
D788 | 91 94 | STA ($94),Y | ||
D78A | C8 | INY | ||
D78B | AD 58 02 | LDA $0258 | Move the record length from REC ($0258) to (DIRBUF) ,Y. | |
D78E | 91 94 | STA ($94),Y | ||
AF50 | D790 | 20 64 D4 | JSR $D464 | JSR to DRTWRT ($D464) to write out the directory sector. |
D793 | 68 | PLA | Pull the original value of LINDX off the stack, store it back in LINDX ($82). and transfer the value into .X. | |
D794 | 85 82 | STA $82 | ||
D796 | AA | TAX | ||
D797 | 68 | PLA | Pull the original value of SA off the stack, store it back in SA ($83) . | |
D798 | 85 83 | STA $83 | ||
D79A | AD 91 02 | LDA $0291 | Load .A with the number of the directory sector containing the new entry from DELSEC ($0291) and store it in ENTSEC ($D8) and in DSEC,X ($0260, X) . | |
D79D | 85 D8 | STA $D8 | ||
D79F | 9D 60 02 | STA $0260,X | ||
D7A2 | AD 92 02 | LDA $0292 | ||
D7A5 | 85 DD | STA $DD | Load .A with the pointer to the start of the new entry from DELIND ($0292) and store it in DIND,X ($0266, X) . | |
D7A7 | 9D 66 02 | STA $0266,X | ||
D7AA | AD 4A 02 | LDA $024A | Load .A with the file type of the new entry from TYPE ($024A) and store it in PATTYP ($E7) . | |
D7AD | 85 E7 | STA $E7 | ||
D7AF | A5 7F | LDA $7F | Load .A with the curre nt drive number from DRVNUM ($7F) and store it in FILDRV ($E2) . | |
D7B1 | 85 E2 | STA $E2 | ||
D7B3 | 60 | RTS | Terminate routine with an RTS. | |
Open a channel from serial busThe open, load, or save command is parsed. A channel is allocated and the directory is searched for the filename specified in the command. |
||||
OPEN | D7B4 | A5 83 | LDA $83 | Move the current secondary address from SA ($83) to TEMPSA ($024C). |
D7B6 | 8D 4C 02 | STA $024C | ||
D7B9 | 20 B3 C2 | JSR $C2B3 | JSR to CMDSET ($C2B3) to set the command string pointers. On return, store the .X value in CMDNUM ($022A) . | |
D7BC | 8E 2A 02 | STX $022A | Load .X with the first character in the command string CMDBUF ($0200). Load .A with the secondary address from TEMPSA ($024C). If the secondary address is not $00, this is not a load so branch to OP021. | |
D7BF | AE 00 02 | LDX $0200 | ||
D7C2 | AD 4C 02 | LDA $024C | ||
D7C5 | D0 2C | BNE $D7F3 | ||
D7C7 | E0 2A | CPX #$2A | Compare the value in .X with $2A ("*") to check if the command is "load the last referenced program". If not $2A, branch to OP021. | |
D7C9 | D0 28 | BNE $D7F3 | ||
D7CB | A5 7E | LDA $7E | Appears to be "load last". Check by loading .A with the last program's track link from PRGTRK ($7E). If .A=0, there is no last program so branch to OP0415 to initialize drive 0. | |
D7CD | F0 4D | BEQ $D81C | ||
OP02 | D7CF | 85 80 | STA $80 | Seems OK, let's load last program. Store the program's track link (in .A) into TRACK ($80) . |
D7D1 | AD 6E 02 | LDA $026E | Move the program's drive number from PRGDRV ($026E) to DRVNUM ($7F) . | |
D7D4 | 85 7F | STA $7F | ||
D7D6 | 85 E2 | STA $E2 | ||
D7D8 | A9 02 | LDA #$02 | Store $82 (program) as the file type in PATTYP ($E7) . | |
D7DA | 85 E7 | STA $E7 | ||
D7DC | AD 6F 02 | LDA $026F | Move the program's sector link from PRGSEC ($026F) into SECTOR ($81). | |
D7DF | 85 81 | STA $81 | ||
D7E1 | 20 00 C1 | JSR $C100 | JSR to SETLDS ($C100) to turn on the drive active LED. | |
D7E4 | 20 46 DC | JSR $DC46 | JSR to OPNRCH ($DC46) to open a read channel . | |
D7E7 | A9 04 | LDA #$04 | Load .A with $04 (2 * program type). OR it with the drive number in DRVNUM ($7F) | |
D7E9 | 05 7F | ORA $7F | ||
ENDRD | D7EB | A6 82 | LDX $82 | Load .X with the number of the active buffer from LINDX ($82) . |
D7ED | 99 EC 00 | STA $00EC,Y | Store the value in .A as the file type in FILTYP,Y ($00EC,Y) . | |
D7F0 | 4C 94 C1 | JMP $C194 | Terminate routine with a JMP to ENDCMD ($C194) . | |
OP021 | D7F3 | E0 24 | CPX #$24 | Compare the byte in .X (the first in the command string) with $24 ("$") to check if we a re to load the directory. If it is NOT "$",branch to OP041. |
D7F5 | D0 1E | BNE $D815 | ||
D7F7 | AD 4C 02 | LDA $024C | We want the directory. But, should we load it or just open it as a SEQ file? Check the secondary address in TEMPSA (024C). If it is not $00, branch to OP04 to open it as a SEQ file. | |
D7FA | D0 03 | BNE $D7FF | ||
D7FC | 4C 55 DA | JMP $DA55 | JMP to LOADIR ($DA55) to load the directory | |
OP04 | D7FF | 20 D1 C1 | JSR $C1D1 | Open the directory as a SEQ file. JSR to SIMPRS ($C1D1) to parse the command string. |
D802 | AD 85 FE | LDA $FE85 | Move the directory's track link from DIRTRK ($FE85) into TRACK ($80). | |
D805 | 85 80 | STA $80 | ||
D807 | A9 00 | LDA #$00 | Zero the desired sector, SECTOR ($81) | |
D809 | 85 81 | STA $81 | ||
D80B | 20 46 DC | JSR $DC46 | JSR to OPNRCH ($DC46) to open the read channel . | |
D80E | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F) and OR it with $02 (2 * the SEQ file type) . | |
D810 | 09 02 | ORA #$02 | ||
D812 | 4C EB D7 | JMP $D7EB | Terminate routine with a JMP to ENDRD ($D7EB) . | |
OP041 | D815 | E0 23 | CPX #$23 | Compare the byte in .X (the first in the command string) with $23 ("#") to check if this is to be a direct access channel If it is NOT "#", branch to OP042. |
D817 | D0 12 | BNE $D82B | ||
D819 | 4C 84 CB | JMP $CB84 | Continue routine with a JMP to OPNBLK ($CB84) . | |
OP0415 | D81C | A9 02 | LDA #$02 | Set the file type flag TYPFLG ($0296) to $02 (program file) . |
D81E | 8D 96 02 | STA $0296 | ||
D821 | A9 00 | LDA #$00 | Zero the current drive number DRVNUM ($7F) and the last job drive number LSTDRV ($028E) . | |
D823 | 85 7F | STA $7F | ||
D825 | 8D 8E 02 | STA $028E | ||
D828 | 20 42 D0 | JSR $D042 | JSR to INITDR ($D042) to initialize drive #0. | |
OP042 | D82B | 20 E5 C1 | JSR $C1E5 | JSR to PRSCLN ($C1E5) to parse the command string to find the colon. |
D82E | D0 04 | BNE $D834 | If none found, branch to OP049 | |
D830 | A2 00 | LDX #$00 | Zero .X and branch to OP20 (always) . | |
D832 | F0 0C | BEQ $D840 | ||
OP049 | D834 | 8A | TXA | Transfer the byte in .X to .A. If the byte is $00. branch to OP10. |
D835 | F0 05 | BEQ $D83C | ||
OP05 | D837 | A9 30 | LDA #$30 | Oops, trouble! Load .A with $30 to indicate a BAD SYNTAX error and JMP to CMDERR ($C1C8) . |
D839 | 4C C8 C1 | JMP $C1C8 | ||
OP10 | D83C | 88 | DEY | Decrement .Y so it points to the " : " If .Y=0, first character is a " : " so branch to OP20. |
D83D | F0 01 | BEQ $D840 | ||
D83F | 88 | DEY | Decrement .Y so it points to the byte just before the " : " . | |
OP20 | D840 | 8C 7A 02 | STY $027A | Store the pointer to the file name (in .Y) into FILTBL ($027A). |
D843 | A9 8D | LDA #$8D | Load .A with $8D (shifted return) and JSR to PARSE ($C268) to parse the rest of the command string. | |
D845 | 20 68 C2 | JSR $C268 | ||
D848 | E8 | INX | Increment .X (file count) and store the result into F2CNT ($0278) . | |
D849 | 8E 78 02 | STX $0278 | ||
D84C | 20 12 C3 | JSR $C312 | JSR to ONEDRV ($C312) to set up one drive and the necessary pointers. | |
D84F | 20 CA C3 | JSR $C3CA | JSR to OPTSCH ($C3CA) to" determine the optimal search pattern, | |
D852 | 20 9D C4 | JSR $C49D | JSR to FFST ($C49D) to search the disk directory for the file entry. | |
D855 | A2 00 | LDX #$00 | ||
D857 | 8E 58 02 | STX $0258 | Zero the record length, REC ($0258) , MODE ($0297) (read mode), and the file type, TYPE ($024A) (deleted file). | |
D85A | 8E 97 02 | STX $0297 | ||
D85D | 8E 4A 02 | STX $024A | ||
D860 | E8 | INX | ||
D861 | EC 77 02 | CPX $0277 | Test the value of F1CNT ($0277). If it is $00, there are NO wild cards in the filename so branch to OP40. | |
D864 | B0 10 | BCS $D876 | ||
D866 | 20 09 DA | JSR $DA09 | JSR to CKTM ($DA09) to set the file type and mode. | |
D869 | E8 | INX | Test the value of F1CNT ($0277). If it is $01, there is only one wild card in the filename so branch to OP40. | |
D86A | EC 77 02 | CPX $0277 | ||
D86D | B0 07 | BCS $D876 | ||
D86F | C0 04 | CPY #$04 | Compare .Y to $04. If .Y=$04, this is a relative file so branch to OP60 to set the record size. | |
D871 | F0 3E | BEQ $D8B1 | ||
D873 | 20 09 DA | JSR $DA09 | JSR to CKTM ($DA09) to set the file type and mode. | |
OP40 | D876 | AE 4C 02 | LDX $024C | Restore the original secondary address into SA ($83) using the value from TEMPSA ($024C) . |
D879 | 86 83 | STX $83 | ||
D87B | E0 02 | CPX #$02 | Test the secondary address, if it is greater or equal to $02, this is not a load or save so branch to OP45. | |
D87D | B0 12 | BCS $D891 | ||
D87F | 8E 97 02 | STX $0297 | This is a load or save. Set MODE ($0297) (0=read; l=write) using the secondary address (0=load; l=save) . | |
D882 | A9 40 | LDA #$40 | Set the write BAM flag, WBAM ($02F9) to $40 to flag that BAM is dirty. | |
D884 | 8D F9 02 | STA $02F9 | ||
D887 | AD 4A 02 | LDA $024A | Load .A with the file type, TYPE ($024A) If it is not $00 (deleted file type) , branch to OP50. NOTE: load & save of files have TYPE set to $00 in $D857. | |
D88A | D0 1B | BNE $D8A7 | ||
D88C | A9 02 | LDA #$02 | Set file type, TYPE ($024A) to $02 (program file type). | |
D88E | 8D 4A 02 | STA $024A | ||
OP45 | D891 | AD 4A 02 | LDA $024A | Load .A with the file type, TYPE ($024A) If it is not $00 (scratched file type) , branch to OP50. |
D894 | D0 11 | BNE $D8A7 | ||
D896 | A5 E7 | LDA $E7 | Load the file type as given in the directory from PATTYP ( $E7). AND it with $07 (file type mask). and store the result as the file type in TYPE ($024A) | |
D898 | 29 07 | AND #$07 | ||
D89A | 8D 4A 02 | STA $024A | ||
D89D | AD 80 02 | LDA $0280 | Test the file's first"track link in FILTRK ($0280). If it is not $00, the file exists so branch to OP50. | |
D8A0 | D0 05 | BNE $D8A7 | ||
D8A2 | A9 01 | LDA #$01 | The file doesn't exist, set TYPE ($024A) to $01 (the default value; a SEQ file) . | |
D8A4 | 8D 4A 02 | STA $024A | ||
OP50 | D8A7 | AD 97 02 | LDA $0297 | Check MODE ($0297). If it is $01, it is write mode so branch to OP75 to write, |
D8AA | C9 01 | CMP #$01 | ||
D8AC | F0 18 | BEQ $D8C6 | ||
D8AE | 4C 40 D9 | JMP $D940 | JMP to OP90 ($D940) to open to read or load. | |
Handle relative file |
||||
OP60 | D8B1 | BC 7A 02 | LDY $027A,X | Load .Y with the pointer from FILTBL,X. |
D8B4 | B9 00 02 | LDA $0200,Y | Load .A with the file's record size as given in the directory from CMDBUF,Y and store it in REC ($0258). | |
D8B7 | 8D 58 02 | STA $0258 | ||
D8BA | AD 80 02 | LDA $0280 | Test if the file's track link in FILTRK ($0280) is $00. If it is NOT $00, the fHandle relative file:ile is present so branch to OP40 to read it. | |
D8BD | D0 B7 | BNE $D876 | ||
D8BF | A9 01 | LDA #$01 | Set the MODE ($0297) to $01 (write mode) and branch to OP40 (always) . | |
D8C1 | 8D 97 02 | STA $0297 | ||
D8C4 | D0 B0 | BNE $D876 | ||
OP75 | D8C6 | A5 E7 | LDA $E7 | Load .A with the file's type as given in the directory from PATTYP ($E7). AND it with $80 to determine if it is a deleted file, and transfer the result to .X. If it is not a deletedfile, branch to OP81 |
D8C8 | 29 80 | AND #$80 | ||
D8CA | AA | TAX | ||
D8CB | D0 14 | BNE $D8E1 | ||
OP77 | D8CD | A9 20 | LDA #$20 | Open to write. Load.A with $20 and test if any bits in .A and the file type in PATTYP ($E7) match If not, branch to OP80. |
D8CF | 24 E7 | BIT $E7 | ||
D8D1 | F0 06 | BEQ $D8D9 | ||
D8D3 | 20 B6 C8 | JSR $C8B6 | JSR to DELDIR ($C8B6) to delete the directory entry andwrite out the revised sector. | |
D8D6 | 4C E3 D9 | JMP $D9E3 | JMP to OPWRIT ($D9E3) to open the channel to write. | |
OP80 | D8D9 | AD 80 02 | LDA $0280 | Load .A with the entry's track link from FILTRK ($0280). If it is not $00, there is an existing file so branch to OP81. |
D8DC | D0 03 | BNE $D8E1 | ||
D8DE | 4C E3 D9 | JMP $D9E3 | File not found but that's OK. JMP to OPWRIT ($D9E3) to open a write channel. | |
OP81 | D8E1 | AD 00 02 | LDA $0200 | Load .A with CMDBUF ($0200), the first byte of the command string. If it equals $40 ("@"), branch to OP82. NOTE: THIS IS WHERE REPLACE FILE COMMAND IS DETECTED! |
D8E4 | C9 40 | CMP #$40 | ||
D8E6 | F0 0D | BEQ $D8F5 | ||
D8E8 | 8A | TXA | Transfer .X value into .A. If it is not $00, branch to OP815. | |
D8E9 | D0 05 | BNE $D8F0 | ||
D8EB | A9 63 | LDA #$63 | Load .A with $63 to indicate a FILE EXISTS ERROR and JMP to CMDERR ($C1C8). | |
D8ED | 4C C8 C1 | JMP $C1C8 | ||
OP815 | D8F0 | A9 33 | LDA #$33 | Load .A with $33 to indicate a bad filename and JMP to CMDERR ($C1C8) . |
D8F2 | 4C C8 C1 | JMP $C1C8 | ||
Replace file routine * may have bug! |
||||
OP82 | D8F5 | A5 E7 | LDA $E7 | Load the file type of the directory entry from PATTYP ($E7). AND it with the file type mask $07. and compare the result with the command string file type in TYPE ($024A). If the file types do not match, branch to OP115 to abort. |
D8F7 | 29 07 | AND #$07 | ||
D8F9 | CD 4A 02 | CMP $024A | ||
D8FC | D0 67 | BNE $D965 | ||
D8FE | C9 04 | CMP #$04 | Compare the file type (in .A) with $04. If it is $04, this is a relative file so branch to OP115 to abort. | |
D900 | F0 63 | BEQ $D965 | ||
D902 | 20 DA DC | JSR $DCDA | JSR to OPNWCH ($DCDA) to open the write channel . | |
D905 | A5 82 | LDA $82 | Move the active buffer number from LINDX ($82) to WLINDX ($0270) . | |
D907 | 8D 70 02 | STA $0270 | ||
D90A | A9 11 | LDA #$11 | Set the secondary address, SA ($83) to $11 (#17) the internal read channel. | |
D90C | 85 83 | STA $83 | ||
D90E | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. | |
D911 | AD 94 02 | LDA $0294 | Load .A with the current value of the pointer into the directory buffer, INDEX ($0294) and JSR to SETPNT ($D4C8) to set the buffer pointers to point to the INDEXth byte. NOTE: at this point INDEX points to the first byte in the entry, the file type. | |
D914 | 20 C8 D4 | JSR $D4C8 | ||
D917 | A0 00 | LDY #$00 | Zero .Y. Then load .A with the file type from (DIRBUF) ,Y; ($94), Y, OR the file type with $20 (set the replace bit). and store the result back in (DIRBUF) ,Y. | |
D919 | B1 94 | LDA ($94),Y | ||
D91B | 09 20 | ORA #$20 | ||
D91D | 91 94 | STA ($94),Y | ||
D91F | A0 1A | LDY #$1A | Load .Y with $1A (#26) and move the new track link from TRACK($80) to (DIRBUF) ,Y | |
D921 | A5 80 | LDA $80 | ||
D923 | 91 94 | STA ($94),Y | ||
D925 | C8 | INY | Increment .Y and move the new sector link from SECTOR ($81) to (DIRBUF) ,Y. | |
D926 | A5 81 | LDA $81 | ||
D928 | 91 94 | STA ($94),Y | ||
D92A | AE 70 02 | LDX $0270 | Load .X with the active buffer number from WLINDX ($0270) . | |
D92D | A5 D8 | LDA $D8 | Load .A with the sector of the directory entry ENTSEC ($D8) and copy it into DSEC,X ($0260, X) . | |
D92F | 9D 60 02 | STA $0260,X | ||
D932 | A5 DD | LDA $DD | Load .A with the pointer to the start of the directory entry ENTIND ($DD) and copy it into DIND,X ($0266 / X). | |
D934 | 9D 66 02 | STA $0266,X | ||
D937 | 20 3B DE | JSR $DE3B | JSR to CURBLK ($DE3B) to set TRACK ($80) and SECTOR ($81) from header of most recently read header. | |
D93A | 20 64 D4 | JSR $D464 | JSR to DRTWRT ($D464) to do direct block write of directory block to disk. | |
D93D | 4C EF D9 | JMP $D9EF | JMP to OPFIN ($D9EF) to finish opening the file. | |
OP90 | D940 | AD 80 02 | LDA $0280 | Test the directory entry's track link in FILTRK ($0280). If it is NOT $00, the file exists so branch to OP100. |
D943 | D0 05 | BNE $D94A | ||
OP95 | D945 | A9 62 | LDA #$62 | Load .A with $62 to indicate a FILE NOT FOUND error and JMP to CMDERR ($C1C8). |
D947 | 4C C8 C1 | JMP $C1C8 | ||
OP100 | D94A | AD 97 02 | LDA $0297 | Compare the value in MODE ($0297) to $03 (open to modify). If MODE=$03 branch to OP110. |
D94D | C9 03 | CMP #$03 | ||
D94F | F0 0B | BEQ $D95C | ||
D951 | A9 20 | LDA #$20 | Check bit 5 of the directory entry's file type. If this bit is set, it flags a file that is already opened (or not closed properly). If the bit is NOT SET, branch to OP110 and carry on. | |
D953 | 24 E7 | BIT $E7 | ||
D955 | F0 05 | BEQ $D95C | ||
D957 | A9 60 | LDA #$60 | Load .A with $60 to indicate a FILE OPEN error and JMP to CMDERR ($C1C8). | |
D959 | 4C C8 C1 | JMP $C1C8 | ||
OP110 | D95C | A5 E7 | LDA $E7 | Load .A with the directory entry's file type from PATTYP ($E7). AND it with $07 to mask off higher order bits, and compare it with the file type specified in the command string from TYPE ($024A) . If the file types match, branch to OP120 |
D95E | 29 07 | AND #$07 | ||
D960 | CD 4A 02 | CMP $024A | ||
D963 | F0 05 | BEQ $D96A | ||
OP115 | D965 | A9 64 | LDA #$64 | Load .A with $64 to indicate a FILE TYPE MISMATCH error and JMP to CMDERR ($C1C8) |
D967 | 4C C8 C1 | JMP $C1C8 | ||
OP120 | D96A | A0 00 | LDY #$00 | Load .Y with $00 and use it to zero F2PTR ($0279) |
D96C | 8C 79 02 | STY $0279 | ||
D96F | AE 97 02 | LDX $0297 | Load .X with the mode from MODE ($0297) | |
D972 | E0 02 | CPX #$02 | ||
D974 | D0 1A | BNE $D990 | ||
D976 | C9 04 | CMP #$04 | If MODE is not $02 (open to append) , branch to OP125. | |
D978 | F0 EB | BEQ $D965 | ||
D97A | B1 94 | LDA ($94),Y | Compare the file type (in .A) with $04. If it is $04,this is a relative file so branch to OP115. | |
D97C | 29 4F | AND #$4F | ||
D97E | 91 94 | STA ($94),Y | ||
D980 | A5 83 | LDA $83 | This applies only to opening to append, Load .A with the file type from (DIRBUF) ,Y ; ($94) ,Y, AND it with $4F, and store it back in (DIRBUF) ,Y. | |
D982 | 48 | PHA | ||
D983 | A9 11 | LDA #$11 | ||
D985 | 85 83 | STA $83 | ||
D987 | 20 3B DE | JSR $DE3B | Save the secondary address from SA ($83) onto the stack and set SA ($83) to $11 (#17, the internal read channel) . | |
D98A | 20 64 D4 | JSR $D464 | JSR to CURBLK ($DE3B) to set TRACK ($80) and SECTOR ($81) from header of most recently read header . | |
D98D | 68 | PLA | JSR to DRTWRT ($D464) to do direct block write of directory block to disk. | |
D98E | 85 83 | STA $83 | ||
OP125 | D990 | 20 A0 D9 | JSR $D9A0 | Pull original secondary address off the stack and restore it in SA ($83). JSR to OPREAD ($D9A0) to open the file for a read. |
D993 | AD 97 02 | LDA $0297 | Check if MODE ($0297) is $02 (append) . If it isn't $'02, branch to OPFIN ($D9EF) | |
D996 | C9 02 | CMP #$02 | ||
D998 | D0 55 | BNE $D9EF | ||
D99A | 20 2A DA | JSR $DA2A | JSR to APPEND ($DA2A) to read to the end of the file. | |
D99D | 4C 94 C1 | JMP $C194 | JMP to ENDCMD ($C194) to terminate. | |
Open a file to read |
||||
OPREAD | D9A0 | A0 13 | LDY #$13 | Copy the relative file values from the directory entry (DIRBUF) ,Y; ($94) ,Y into their RAM variable locations: Track for side sector to TRKSS ($0259) Sector for side sector to SECSS ($025A) |
D9A2 | B1 94 | LDA ($94),Y | ||
D9A4 | 8D 59 02 | STA $0259 | ||
D9A7 | C8 | INY | ||
D9A8 | B1 94 | LDA ($94),Y | ||
D9AA | 8D 5A 02 | STA $025A | ||
D9AD | C8 | INY | ||
D9AE | B1 94 | LDA ($94),Y | Load .A with the record size from the directory entry. Load .X with the size from the command string, REC ($0258) . | |
D9B0 | AE 58 02 | LDX $0258 | ||
D9B3 | 8D 58 02 | STA $0258 | Store the value in .A into REC ($0258) . | |
D9B6 | 8A | TXA | Transfer the value from .X into .A. If the command string size is $00, branch to OP130 (defaults to entry size) . | |
D9B7 | F0 0A | BEQ $D9C3 | ||
D9B9 | CD 58 02 | CMP $0258 | Compare the two record lengths. If they are equal, branch to OP130. | |
D9BC | F0 05 | BEQ $D9C3 | ||
D9BE | A9 50 | LDA #$50 | Record lengths do not match, load .A with $50 to indicate a READ PAST END OF FILE error and JSR to CMDERR ($C1C8). | |
D9C0 | 20 C8 C1 | JSR $C1C8 | ||
OP130 | D9C3 | AE 79 02 | LDX $0279 | Load .X with the pointer F2PTR ($0279). |
D9C6 | BD 80 02 | LDA $0280,X | Copy the track link from FILTRK,X ($0280, X) to TRACK ($80). | |
D9C9 | 85 80 | STA $80 | ||
D9CB | BD 85 02 | LDA $0285,X | Copy the sector link from FILSEC,X ($0285, X) to SECTOR ($81). | |
D9CE | 85 81 | STA $81 | ||
D9D0 | 20 46 DC | JSR $DC46 | JSR to OPNRCH ($DC46) to open a read channel . | |
D9D3 | A4 82 | LDY $82 | Load .Y with the active buffer number from LINDX ($82) . | |
D9D5 | AE 79 02 | LDX $0279 | Load .X with the pointer F2PTR ($0279). | |
D9D8 | B5 D8 | LDA $D8,X | Copy the directory sector containing the entry from ENTSEC,X ($D8,X) to DSEC,Y ($0260, Y) . | |
D9DA | 99 60 02 | STA $0260,Y | ||
D9DD | B5 DD | LDA $DD,X | ||
D9DF | 99 66 02 | STA $0266,Y | Copy the pointer to the entry in the directory sector from ENTIND,X ($DD,X) to DIND,Y ($0266, Y) . | |
D9E2 | 60 | RTS | Terminate the routine with an RTS. | |
Open a file to write |
||||
OPWRIT | D9E3 | A5 E2 | LDA $E2 | Load .A with the drive number for the file from FILDRV ($E2), AND it with $01 to mask off non-drive bits, and store the result, as the current drive in DRVNUM ($7F) . |
D9E5 | 29 01 | AND #$01 | ||
D9E7 | 85 7F | STA $7F | ||
D9E9 | 20 DA DC | JSR $DCDA | JSR to OPNWCH ($DCDA) to open a write channel . | |
D9EC | 20 E4 D6 | JSR $D6E4 | JSR to ADDFIL ($D6E4) to add the entry to the directory. | |
OPFIN | D9EF | A5 83 | LDA $83 | If the secondary address is greater than $01. it is a not a program file so branch to OPF1. |
D9F1 | C9 02 | CMP #$02 | ||
D9F3 | B0 11 | BCS $DA06 | ||
D9F5 | 20 3E DE | JSR $DE3E | JSR to GETHDR ($DE3E) to set up TRACK and SECTOR values from the last header read. | |
D9F8 | A5 80 | LDA $80 | Copy the track link from TRACK ($80) to PRGTRK ($7E) . | |
D9FA | 85 7E | STA $7E | ||
D9FC | A5 7F | LDA $7F | Copy the file drive from DRVNUM ($7F) to PRGDRV ($026E) . | |
D9FE | 8D 6E 02 | STA $026E | ||
DA01 | A5 81 | LDA $81 | Copy the sector link from SECTOR ($81) to PRGSEC ($026F) . | |
DA03 | 8D 6F 02 | STA $026F | ||
OPF1 | DA06 | 4C 99 C1 | JMP $C199 | Terminate routine with a JMP to ENDSAV ($C199) . |
Check mode or file type |
||||
CKTM | DA09 | BC 7A 02 | LDY $027A,X | Load .Y with the pointer from FILTBL,X. Load .A with the mode or file type from the command string, CMDBUF,Y. Load .Y with $04, the number of modes. |
DA0C | B9 00 02 | LDA $0200,Y | ||
DA0F | A0 04 | LDY #$04 | ||
CKM1 | DA11 | 88 | DEY | Loop to compare mode requested with the table of modes, MODLST,Y ($FEB2,Y). If no match is found, branch to CKM2. If a match is found, fall through.
|
DA12 | 30 08 | BMI $DA1C | ||
DA14 | D9 B2 FE | CMP $FEB2,Y | ||
DA17 | D0 F8 | BNE $DA11 | ||
DA19 | 8C 97 02 | STY $0297 | Store .Y counter (0-3) in MODE ($0297) | |
CKM2 | DA1C | A0 05 | LDY #$05 | Loop to compare type requested with the table of types, TPLST,Y ($FEB6,Y). If no match is found, branch to CKT2. If a match is found, fall through.
|
DA1E | 88 | DEY | ||
DA1F | 30 08 | BMI $DA29 | ||
DA21 | D9 B6 FE | CMP $FEB6,Y | ||
DA24 | D0 F8 | BNE $DA1E | ||
DA26 | 8C 4A 02 | STY $024A | Store .Y counter (0-3) in TYPE ($024A) | |
CKT2 | DA29 | 60 | RTS | Terminate the routine with an RTS. |
Append information to the end of a fileReads through old file to end. |
||||
APPEND | DA2A | 20 39 CA | JSR $CA39 | JSR to GCBYTE ($CA39) tc get a byte from the data channel. |
DA2D | A9 80 | LDA #$80 | Test if we are at the end of file. If not, loop back to APPEND. | |
DA2F | 20 A6 DD | JSR $DDA6 | ||
DA32 | F0 F6 | BEQ $DA2A | ||
DA34 | 20 95 DE | JSR $DE95 | JSR to RDLNK ($DE95) to set TRACK ($80) and SECTOR ($81) from the track and sector links in the last block. NOTE: TRACK will be $00 and SECTOR will be a pointer to the end of the file. | |
DA37 | A6 81 | LDX $81 | Load .X with the end of file pointer from SECTOR ($81), increment it by 1, and transfer the result to .A. If the new value of the pointer is not $00, there is space left at the end of this sector so branch to AP30. | |
DA39 | E8 | INX | ||
DA3A | 8A | TXA | ||
DA3B | D0 05 | BNE $DA42 | ||
DA3D | 20 A3 D1 | JSR $D1A3 | No space left in this sector so JSR to WRT0 ($D1A3) to get the next sector. Load .A with $02 so it. points to the start of the data area for this new sector. | |
DA40 | A9 02 | LDA #$02 | ||
AP30 | DA42 | 20 C8 D4 | JSR $D4C8 | JSR to SETPNT ($D4C8) to set the active buffer pointers. |
DA45 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) and store $01 (channel ready at the end of file) in the channel status flag CHNRDY,X ($F2,X). | |
DA47 | A9 01 | LDA #$01 | ||
DA49 | 95 F2 | STA $F2,X | ||
DA4B | A9 80 | LDA #$80 | Load .X with the sec. address SA ($83) . Load .A with $80, OR it with the active buffer number in LINDX ($82). and store the result in LINTAB,X ($022B,X) to indicate that this is now a write file. | |
DA4D | 05 82 | ORA $82 | ||
DA4F | A6 83 | LDX $83 | ||
DA51 | 9D 2B 02 | STA $022B,X | ||
DA54 | 60 | RTS | Terminate the routine with an RTS. | |
Load the directory ($) |
||||
LOADIR | DA55 | A9 0C | LDA #$0C | Store $0C (load) as the command code in CMDNUM ($022A) . |
DA57 | 8D 2A 02 | STA $022A | ||
DA5A | A9 00 | LDA #$00 | Load .A with $00 (load only drive #0) | |
DA5C | AE 74 02 | LDX $0274 | Load .X with the command length from CMDSIZ ($0274) and decrement " the length in .X by 1. If the result is $00, branch to LD02 to load complete directory for drive 0. | |
DA5F | CA | DEX | ||
DA60 | F0 0B | BEQ $DA6D | ||
LD01 | DA62 | CA | DEX | Decrement the length in .X by 1. If the result is still not $00, this must be a selective load by name so branch to LD03 |
DA63 | D0 21 | BNE $DA86 | ||
DA65 | AD 01 02 | LDA $0201 | Load .A with the second character in the command string from CMDBUF+i ($0201) and JSR to TST0V1 ($C3BD) to test if the character is an ASCII "0" or "1". If not, branch to LD03 to load by name. | |
DA68 | 20 BD C3 | JSR $C3BD | ||
DA6B | 30 19 | BMI $DA86 | ||
LD02 | DA6D | 85 E2 | STA $E2 | Store the drive number desired (in .A) into FILDRV ($E2) . |
DA6F | EE 77 02 | INC $0277 | Increment F1CNT ($0277). F2CNT ($0278), and FILTBL ($027A) . | |
DA72 | EE 78 02 | INC $0278 | ||
DA75 | EE 7A 02 | INC $027A | ||
DA78 | A9 80 | LDA #$80 | Store $80 in PATTYP ($E7) to represent the file type. | |
DA7A | 85 E7 | STA $E7 | ||
DA7C | A9 2A | LDA #$2A | Store $2A ( " * " ) as the first two b>tes in the command string CMDBUF ($0200) and CMDBUF+1 ($0201) | |
DA7E | 8D 00 02 | STA $0200 | ||
DA81 | 8D 01 02 | STA $0201 | ||
DA84 | D0 18 | BNE $DA9E | Branch always to LD10. | |
LD03 | DA86 | 20 E5 C1 | JSR $C1E5 | JSR to PRSCLN ($C2DC) to find the colon in the command string. If no colon is found. branch to LD05. |
DA89 | D0 05 | BNE $DA90 | ||
DA8B | 20 DC C2 | JSR $C2DC | Colon found so JSR to CMDRST ($C2DC) to zero all command string variables. | |
DA8E | A0 03 | LDY #$03 | Lead .Y with $03. | |
LD05 | DA90 | 88 | DEY | Decrement .Y twice and store the result, in FILTBL ($027A) . |
DA91 | 88 | DEY | ||
DA92 | 8C 7A 02 | STY $027A | ||
DA95 | 20 00 C2 | JSR $C200 | JSR to TC35 ($C200) to parse and set- up the tables. | |
DA98 | 20 98 C3 | JSR $C398 | JSF to FS1SET ($C398) to set pointers to file name and check type. | |
DA9B | 20 20 C3 | JSR $C320 | JSR to ALLDRS ($C320) to set up all drives required. | |
LD10 | DA9E | 20 CA C3 | JSR $C3CA | JSR to OPTSCH ($C3CA) to determine the best drive search pattern. |
DAA1 | 20 B7 C7 | JSR $C7B7 | JSR to NEWDIR ($C7B7) to read in BAM and set up disk name, ID, etc as first line in directory. | |
DAA4 | 20 9D C4 | JSR $C49D | JSR to FFST ($C49D) to find file start entry. | |
LD20 | DAA7 | 20 9E EC | JSR $EC9E | JSR to STDIR ($EC9E) to start the directory loading function. |
DAAA | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read first byte from the buffer. | |
DAAD | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DAAF | 9D 3E 02 | STA $023E,X | Store the first byte (in .A) into CHNDAT,X ($023E,X) . | |
DAB2 | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F) and use this value to set the last job drive LSTDRV ($028E) . | |
DAB4 | 8D 8E 02 | STA $028E | ||
DAB7 | 09 04 | ORA #$04 | OR the drive number in .A with $04 and store the result as the file type in FILTYP,X ($EC,X) . | |
DAB9 | 95 EC | STA $EC,X | ||
DABB | A9 00 | LDA #$00 | Zero BUFTAB+CBPTR ($A3). Note: CBPTR is the command buffer pointer ($0A). | |
DABD | 85 A3 | STA $A3 | ||
DABF | 60 | RTS | Terminate the routine with an RTS. | |
Close the file related to the specified secondary address |
||||
CLOSE | DAC0 | A9 00 | LDA #$00 | Zero the write BAM flag, WBAM ($02F9). |
DAC2 | 8D F9 02 | STA $02F9 | ||
DAC5 | A5 83 | LDA $83 | If secondary address, SA ($83) is not zero (directory load). branch to CLS10 | |
DAC7 | D0 0B | BNE $DAD4 | ||
DAC9 | A9 00 | LDA #$00 | Close directory: Zero the directory listing flag DIRLST ($0254) and JSR to FRECHN ($D227) to free the channel. | |
DACB | 8D 54 02 | STA $0254 | ||
DACE | 20 27 D2 | JSR $D227 | ||
CLS05 | DAD1 | 4C DA D4 | JMP $D4DA | JMP to FREICH ($D4DA) t o free the internal channel and terminate routine. |
CLS10 | DAD4 | C9 0F | CMP #$0F | If secondary address (in .A) is $0F(#15) branch to CLSALL to close all files. |
DAD6 | F0 14 | BEQ $DAEC | ||
DAD8 | 20 02 DB | JSR $DB02 | JSR to CLSCHN ($DB02) to close channel. | |
DADB | A5 83 | LDA $83 | If secondary address in SA ($83) is $01 (save). branch to CLS05to close the internal channel and exit. | |
DADD | C9 02 | CMP #$02 | ||
DADF | 90 F0 | BCC $DAD1 | ||
DAE1 | AD 6C 02 | LDA $026C | Check the error status in ERWORD ($026C) If status is not $00, the last command produced an error so branch to CLS15. | |
DAE4 | D0 03 | BNE $DAE9 | ||
DAE6 | 4C 94 C1 | JMP $C194 | JMP to ENDCMD ($C194) to end command. | |
CLS15 | DAE9 | 4C AD C1 | JMP $C1AD | Error so JMP to SCREN1 ($C1AD) |
Close all files: (when CMD closed) |
||||
CLSALL | DAEC | A9 0E | LDA #$0E | Set secondary address, SA ($83) to $0E. |
DAEE | 85 83 | STA $83 | ||
CLS20 | DAF0 | 20 02 DB | JSR $DB02 | JSR to CLSCHN ($DB02) to close channel. |
DAF3 | C6 83 | DEC $83 | Decrement SA ($83). If more secondary addresses to do (SA>=0) loop to CLS20. | |
DAF5 | 10 F9 | BPL $DAF0 | ||
DAF7 | AD 6C 02 | LDA $026C | Check the error status in ERWORD ($026C) If status is net $00, the last command produced an error so branch to CLS25. | |
DAFA | D0 03 | BNE $DAFF | ||
DAFC | 4C 94 C1 | JMP $C194 | JMP to ENDCMD ($C194) to end command. | |
CLS25 | DAFF | 4C AD C1 | JMP $C1AD | Error so JMP to SCRENl ($C1AD) |
CLSCHN | DB02 | A6 83 | LDX $83 | Close file with specified sec. address Load .X with the secondary address from SA ($83) . |
DB04 | BD 2B 02 | LDA $022B,X | Load .A with the channel status from LINTAB,X ($022B,X). If the status is not $FF (closed), branch to CLSC28. | |
DB07 | C9 FF | CMP #$FF | ||
DB09 | D0 01 | BNE $DB0C | Channel already closed so terminate routine with an RTS. | |
DB0B | 60 | RTS | ||
CLSC28 | DB0C | 29 0F | AND #$0F | AND the channel status (in .A) with $0F to leave only the buffer number and store the result in LINDX ($82) . |
DB0E | 85 82 | STA $82 | ||
DB10 | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to determine the file type (returned in .A) . | |
DB13 | C9 07 | CMP #$07 | If file type is $07 (direct channel) branch to CLSC30. | |
DB15 | F0 0F | BEQ $DB26 | ||
DB17 | C9 04 | CMP #$04 | If file type is $04 (relative file) branch to CLSREL. | |
DB19 | F0 11 | BEQ $DB2C | ||
DB1B | 20 07 D1 | JSR $D107 | JSR to FNDWCK ($D107) to find an unused write channel. If none found, branch to | |
DB1E | B0 09 | BCS $DB29 | ||
DB20 | 20 62 DB | JSR $DB62 | JSR to CLSWRT ($DB62) to close off sequential write. | |
DB23 | 20 A5 DB | JSR $DBA5 | JSR to CLSDIR ($DBA5) to close directory | |
CLSC30 | DB26 | 20 F4 EE | JSR $EEF4 | JSR to MAPOUT ($EEF4) to write out. BAM. |
CLSC31 | DB29 | 4C 27 D2 | JMP $D227 | JMP to FRECHN ($D227) to free channel and terminate the command. |
CLSREL | DB2C | 20 F1 DD | JSR $DDF1 | Sub to close relative file: JSR to SCRUB ($DDF1) to write out BAM if it is dirty (RAM version modified) . |
DB2F | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to set up double buffering and read ahead. | |
DB32 | 20 CB E1 | JSR $E1CB | JSR to SSEND ($E1CB) to position side sector & buffer table pointer to the end of the last record. | |
DB35 | A6 D5 | LDX $D5 | Load .X with the side sector number from SSNUM ($D5), store this byte in T4($73), and increment T4 by 1. | |
DB37 | 86 73 | STX $73 | ||
DB39 | E6 73 | INC $73 | ||
DB3B | A9 00 | LDA #$00 | Zero T1 ($70) and T2 ($71). | |
DB3D | 85 70 | STA $70 | ||
DB3F | 85 71 | STA $71 | ||
DB41 | A5 D6 | LDA $D6 | Load .A with the pointer to the side sector value in the directory buffer from SSIND ($D6), set the carry flag, subtract $0E (the side sector offset-2) , and store the result in T3 ($72) . | |
DB43 | 38 | SEC | ||
DB44 | E9 0E | SBC #$0E | ||
DB46 | 85 72 | STA $72 | ||
DB48 | 20 51 DF | JSR $DF51 | JSR to SSCALC ($DF51) to calculate the number of side sector blocks needed. | |
DB4B | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DB4D | A5 70 | LDA $70 | Move the lo byte of the number of side sector blocks from Tl ($70) to NBKL,X ($B5,X) and the hi byte from T2 ($71) to NBKH,X ($BB,X). | |
DB4F | 95 B5 | STA $B5,X | ||
DB51 | A5 71 | LDA $71 | ||
DB53 | 95 BB | STA $BB,X | ||
DB55 | A9 40 | LDA #$40 | Load .A with $40 (the dirty flag for a relative record flag) and JSR to TSTFLG ($DDA6) to test if relative record must be written out. If not, branch to CLSR1 . | |
DB57 | 20 A6 DD | JSR $DDA6 | ||
DB5A | F0 03 | BEQ $DB5F | ||
DB5C | 20 A5 DB | JSR $DBA5 | JSR to CLSDIR ($DBA5) to close the directory file. | |
CLSR1 | DB5F | 4C 27 D2 | JMP $D227 | JMP to FRECHN ($D227) to clear the channel and terminate routine. |
Close a sequential file write channel |
||||
CLSWRT | DB62 | A6 82 | LDX $82 | Lead .X with the active buffer number from LINDX ($82) . |
DB64 | B5 B5 | LDA $B5,X | Load .A with the number of bytes written in this sector from NBKL,X ($B5,X) and OR .A with the number of data blocks written from NBKL,X ($B5,X). If the result is not $00. at least one block of the file has been written so branch to CLSW10. | |
DB66 | 15 BB | ORA $BB,X | ||
DB68 | D0 0C | BNE $DB76 | ||
DB6A | 20 E8 D4 | JSR $D4E8 | No blocks have been written so JSF to GETPNT ($D4E8) to get the pointer into the data buffer (returned in .A). If this value is greater than two, at least one byte has been written so branch to CLSW10. | |
DB6D | C9 02 | CMP #$02 | ||
DB6F | D0 05 | BNE $DB76 | ||
DB71 | A9 0D | LDA #$0D | No bytes have been written so load .A with $0D (carriage return) and JSR to PUTBYT ($CFF1) to write it out to the data buffer. | |
DB73 | 20 F1 CF | JSR $CFF1 | ||
CLSW10 | DB76 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to get the pointer into the data buffer (returned in .A) . If the pointer value is not $02, the buffer is not empty so branch to CLSW20. |
DB79 | C9 02 | CMP #$02 | ||
DB7B | D0 0F | BNE $DB8C | ||
DB7D | 20 1E CF | JSR $CF1E | Since we have an empty buffer, JSR to DBLBUF ($CF1E) to switch buffers. | |
DB80 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DB82 | B5 B5 | LDA $B5,X | Load .A with the number of bytes written in this sector from NBKL,X ($B5,X). If this value is not equal to $00, branch to CLSW15. | |
DB84 | D0 02 | BNE $DB88 | ||
DB86 | D6 BB | DEC $BB,X | Decrement the number of data blocks written in NBKH,X ($BB,X) by 1. | |
CLSW15 | DB88 | D6 B5 | DEC $B5,X | Decrement the number of bytes written in this sector, NBKL,X ($B5,X) by 1. |
DB8A | A9 00 | LDA #$00 | Load .A with $00. | |
CLSW20 | DB8C | 38 | SEC | Set the carry flag, subtract $01 from the number of bytes written in this sector (.A), and save the result, on the stack. |
DB8D | E9 01 | SBC #$01 | ||
DB8F | 48 | PHA | ||
DB90 | A9 00 | LDA #$00 | Load .A with $00 and JSR to SETPNT ($D4C8) to set the buffer pointers to the first byte in the data buffer (the track link) . | |
DB92 | 20 C8 D4 | JSR $D4C8 | ||
DB95 | 20 F1 CF | JSR $CFF1 | JSR to PUTBYT ($CFF1) to write $00 out as the track link. | |
DB98 | 68 | PLA | Pull the bytes written from the stack. | |
DB99 | 20 F1 CF | JSR $CFF1 | JSR to PUTBYT ($CFF1) to write out the bytes in this sector as the sector link. | |
DB9C | 20 C7 D0 | JSR $D0C7 | JSR to WRTBUF ($D0C7) to write the data buffer out to disk. | |
DB9F | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the write job to be completed. | |
DBA2 | 4C 1E CF | JMP $CF1E | JMP to DBLBUF ($CF1E) to make sure that both buffers are OK. | |
Close directory after writing file |
||||
CLSDIR | DBA5 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82). Save this value into WL1NDX ($0270) . |
DBA7 | 8E 70 02 | STX $0270 | ||
DBAA | A5 83 | LDA $83 | Save the current secondary address from SA ($83) onto the stack. | |
DBAC | 48 | PHA | ||
DBAD | BD 60 02 | LDA $0260,X | Copy the sector of the directory entry for the file from DSEC,X ($0260, X) into SECTOR ($81) . | |
DBB0 | 85 81 | STA $81 | ||
DBB2 | BD 66 02 | LDA $0266,X | Copy the pointer to the directory entry for the file from DIND,X ($0266, X) into INDEX ($0294) . | |
DBB5 | 8D 94 02 | STA $0294 | ||
DBB8 | B5 EC | LDA $EC,X | Load .A with the file type from FILTYP,X ($EC,X), AND it with $01 to mask off the non-drive bits, and store the result as the current drive number in DRVNUM ($7F) | |
DBBA | 29 01 | AND #$01 | ||
DBBC | 85 7F | STA $7F | ||
DBBE | AD 85 FE | LDA $FE85 | Copy the directory track number (#18) from DIRTRK ($FE85) into TRACK ($80). | |
DBC1 | 85 80 | STA $80 | ||
DBC3 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
DBC6 | 48 | PHA | Save the active buffer number onto the stack and into JOBNUM ($F9) . | |
DBC7 | 85 F9 | STA $F9 | ||
DBC9 | 20 60 D4 | JSR $D460 | JSR to DIRTRD ($D460) to read in the directory sector containing the entry. | |
DBCC | A0 00 | LDY #$00 | Load .Y with $00. | |
DBCE | BD E0 FE | LDA $FEE0,X | Load .A with the hi byte of the pointer to the active buffer from BUFIND,X ($FEE0,X) and store it in R0+1 ($87). | |
DBD1 | 85 87 | STA $87 | ||
DBD3 | AD 94 02 | LDA $0294 | Complete the pointer into the directory buffer by copying the lo byte of the pointer from INDEX ($0294) to R0 ($86) . | |
DBD6 | 85 86 | STA $86 | ||
DBD8 | B1 86 | LDA ($86),Y | Load .A with the file type from the directory entry (R0),Y, AND it with $20, and checking if the result is $00. If it is $00, this is NOT a replace so branch to CLSD5 . | |
DBDA | 29 20 | AND #$20 | ||
DBDC | F0 43 | BEQ $DC21 | ||
|
||||
DBDE | 20 25 D1 | JSR $D125 | JSR to TYPF1L ($D125) to determine the file type (returned in .A) . | |
DBE1 | C9 04 | CMP #$04 | If file type is $04 (a relative file) branch to CLSD6 . | |
DBE3 | F0 44 | BEQ $DC29 | ||
DBE5 | B1 86 | LDA ($86),Y | Load .A with the file type from R0,Y, AND it with $8F to mask off the replace bit, and store the result back in R0,Y. | |
DBE7 | 29 8F | AND #$8F | ||
DBE9 | 91 86 | STA ($86),Y | ||
DBEB | C8 | INY | Increment .Y. The pointer at (R0) ,Y now points to the old track link. | |
DBEC | B1 86 | LDA ($86),Y | Copy the old track link from (R0) ,Y to into TRACK ($80) . | |
DBEE | 85 80 | STA $80 | ||
DBF0 | 84 71 | STY $71 | Store the .Y value into TEMP+2 ($71) . | |
DBF2 | A0 1B | LDY #$1B | Load .Y with $1B (#27). The pointer at (R0) ,Y now points to the replacement sector link. | |
DBF4 | B1 86 | LDA ($86),Y | Load .A with the replacement sector link from (R0) ,Y and save it on the stack. | |
DBF6 | 48 | PHA | ||
DBF7 | 88 | DEY | Decrement .Y. The pointer at (R0) ,Y now points to the replacement track link. | |
DBF8 | B1 86 | LDA ($86),Y | Load .A with the replacement track link. If this link is NOT $00, branch to CLSD4 | |
DBFA | D0 0A | BNE $DC06 | ||
DBFC | 85 80 | STA $80 | Trouble! Replacement track link should never be $00. So put replacement track link in TRACK ($80) . | |
DBFE | 68 | PLA | Pull replacement sector link off the stack and put it in SECTOR ($81) . | |
DBFF | 85 81 | STA $81 | ||
DC01 | A9 67 | LDA #$67 | Load .A with $67 to indicate a SYSTEM TRACK OR SECTOR error and JMP to CMDER2 ($E645) . | |
DC03 | 20 45 E6 | JSR $E645 | ||
CLSD4 | DC06 | 48 | PHA | Push the replacement track link onto the stack. |
DC07 | A9 00 | LDA #$00 | Load .A with $00. Zero the replacement- track link in the entry (R0) ,Y. | |
DC09 | 91 86 | STA ($86),Y | ||
DC0B | C8 | INY | Increment .Y. | |
DC0C | 91 86 | STA ($86),Y | Zero replacement sector link in (R0) ,Y . | |
DC0E | 68 | PLA | Pull the replacement track link off the stack. | |
DC0F | A4 71 | LDY $71 | Load .Y with the original pointer value from TEMP+2 ($71). Note: pointer at (R0) ,Y now points to the second byte of the entry, the track link. | |
DC11 | 91 86 | STA ($86),Y | Store the replacement track link as the final track link in (R0) ,Y . | |
DC13 | C8 | INY | Increment .Y. Note: the pointer at (R0) ,Y now points to the third byte of the entry, the sector link. | |
DC14 | B1 86 | LDA ($86),Y | Move the old sector link from (R0) ,Y to SECTOR ($81) . | |
DC16 | 85 81 | STA $81 | ||
DC18 | 68 | PLA | Pull the replacement sector link off the stack and store it as the final sector link in (R0) ,Y. | |
DC19 | 91 86 | STA ($86),Y | ||
DC1B | 20 7D C8 | JSR $C87D | JSR to DEIFIL ($C87D) to delete the old file from the BAM by following the track and sector links. | |
DC1E | 4C 29 DC | JMP $DC29 | JSR to CLSD6 ($DC29) to finish closing. | |
CLSD5 | DC21 | B1 86 | LDA ($86),Y | Load .A with the file type from (R0) ,Y , AND it with $0F to mask off any high order bits, OR it with $80 to set the closed bit, and store the result back in (R0) ,Y. |
DC23 | 29 0F | AND #$0F | ||
DC25 | 09 80 | ORA #$80 | ||
DC27 | 91 86 | STA ($86),Y | ||
CLSD6 | DC29 | AE 70 02 | LDX $0270 | Load .X with the active buffer number that was saved into WLINDX ($0270) . |
DC2C | A0 1C | LDY #$1C | Load .Y with $1B (#27). The pointer at (R0) ,Y now points to the low byte of the number of blocks in the file. | |
DC2E | B5 B5 | LDA $B5,X | Copy the lo byte of the number of blocks from NBKL,X ($B5,X) to (R0),Y. | |
DC30 | 91 86 | STA ($86),Y | ||
DC32 | C8 | INY | Increment .Y. | |
DC33 | B5 BB | LDA $BB,X | Copy the hi byte of the number of blocks from NBKH,X ($BB,X) to (R0) ,Y. | |
DC35 | 91 86 | STA ($86),Y | ||
DC37 | 68 | PLA | Pull the original buffer number off the stack and transfer it into .X. | |
DC38 | AA | TAX | ||
DC39 | A9 90 | LDA #$90 | Load .A with $90 (write job code) and OR it with the drive number in DRVNUM($7F). | |
DC3B | 05 7F | ORA $7F | ||
DC3D | 20 90 D5 | JSR $D590 | JSR to DOIT ($D590) to write out the revised directory sector. | |
DC40 | 68 | PLA | Pull the original secondary address off the stack and transfer it into SA ($83), | |
DC41 | 85 83 | STA $83 | ||
DC43 | 4C 07 D1 | JMP $D107 | JMP to FNDWCH ($D107) to exit. | |
Open read channel with two buffers |
||||
OPNRCH | DC46 | A9 01 | LDA #$01 | Sets secondary address in LINTAB and initializes all pointers, including the ones for a relative file. Load .A with $01 and JSR to GETRCH ($D1E2) to set up one read channel |
DC48 | 20 E2 D1 | JSR $D1E2 | ||
DC4B | 20 B6 DC | JSR $DCB6 | JSR to INITP ($DCB6) to clear pointers. | |
DC4E | AD 4A 02 | LDA $024A | Load .A with the file type and save this value on the stack. | |
DC51 | 48 | PHA | ||
DC52 | 0A | ASL | Multiply the file type in .A by 2 (ASL) , OR it with the current drive in DRVNUM ($7F) and store it in FILTYP,X to set the file type. | |
DC53 | 05 7F | ORA $7F | ||
DC55 | 95 EC | STA $EC,X | ||
DC57 | 20 9B D0 | JSR $D09B | JSR to STRRD ($D09B) to read the first- one or two blocks in the file. | |
DC5A | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DC5C | A5 80 | LDA $80 | Load .A with the current track number from TRACK ($80). If the track number is not $00 (not the last block in the file), branch to CR10. | |
DC5E | D0 05 | BNE $DC65 | ||
DC60 | A5 81 | LDA $81 | Load .A with the current sector number from SECTOR ($81). Since TRACK=$00, this is the pointer to the last character in the file. Store this value in LSTCHR,X ($0244, X) . | |
DC62 | 9D 44 02 | STA $0244,X | ||
OR10 | DC65 | 68 | PLA | Pull the original file type off the stack. If this is not a relative file, branch to OR30. |
DC66 | C9 04 | CMP #$04 | ||
DC68 | D0 3F | BNE $DCA9 | ||
DC6A | A4 83 | LDY $83 | Load .Y with the secondary address from SA ($83). Load the channel type from LINTAB, Y ($022B,Y), OR it with $40 to mark it as a READ/WRITE file, and store the channel type back in LINTAB, Y. | |
DC6C | B9 2B 02 | LDA $022B,Y | ||
DC6F | 09 40 | ORA #$40 | ||
DC71 | 99 2B 02 | STA $022B,Y | ||
DC74 | AD 58 02 | LDA $0258 | Copy the record size from REC ($0258) into RS,X ($C7,X) . | |
DC77 | 95 C7 | STA $C7,X | ||
DC79 | 20 8E D2 | JSR $D28E | JSR to GETBUF ($D28E) to set up a buffer for the side sectors. If a buffer is available, branch to OR20. | |
DC7C | 10 03 | BPL $DC81 | ||
DC7E | 4C 0F D2 | JMP $D20F | Since no buffer is available for the side sectors, abort with a JMP to GBERR ($D20F) . | |
OR20 | DC81 | A6 82 | LDX $82 | Load .X with the active buffer number (side sector buffer) from LINDX ($82). |
DC83 | 95 CD | STA $CD,X | Store the side sector buffer number in SS,X ($CD,X) . | |
DC85 | AC 59 02 | LDY $0259 | Copy the side sector track link from TRKSS ($0259) into TRACK ($80). | |
DC88 | 84 80 | STY $80 | ||
DC8A | AC 5A 02 | LDY $025A | Copy the side sector sector link from SECSS ($025A) into SECTOR ($81). | |
DC8D | 84 81 | STY $81 | ||
DC8F | 20 D3 D6 | JSR $D6D3 | JSR to SETH ($D6D3) to set up the side sector header image. | |
DC92 | 20 73 DE | JSR $DE73 | JSR to RDSS ($DE73) to read in the side sector block. | |
DC95 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the job to be completed. | |
OROW | DC98 | A6 82 | LDX $82 | Load .X with the active buffer number (side sector buffer) from LINDX ($82) . |
DC9A | A9 02 | LDA #$02 | Set the next record pointer in the side sector buffer NR,X ($C1,X) to $02. | |
DC9C | 95 C1 | STA $C1,X | ||
DC9E | A9 00 | LDA #$00 | ||
DCA0 | 20 C8 D4 | JSR $D4C8 | Load .A with $00 and JSR to SETPNT ($D4C8) to set the buffer pointers to the start of the side sector buffer. | |
DCA3 | 20 53 E1 | JSR $E153 | JSR to RD4C ($E153) to set up the first record. | |
DCA6 | 4C 3E DE | JMP $DE3E | JMP to GETHDR ($DE3E) to restore the track and sector pointers and exit. | |
OR30 | DCA9 | 20 56 D1 | JSR $D156 | JSR to RDBYT ($D156) to read a byte. |
DCAC | A6 82 | LDX $82 | Load .X with the active buffer number (side sector buffer) from LINDX ($82) . | |
DCAE | 9D 3E 02 | STA $023E,X | Store the data byte (in .A) into CHNDAT,X ($023E,X) . | |
DCB1 | A9 88 | LDA #$88 | Store $88 (ready to talk) as the channel status in CHNRDY,X ($F2,X). | |
DCB3 | 95 F2 | STA $F2,X | ||
DCB5 | 60 | RTS | Terminate routine with an RTS. | |
Initialize variables for open channel |
||||
INITP | DCB6 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . |
DCB8 | B5 A7 | LDA $A7,X | Load buffer number from BUF0,X ($A7,X), multiply it by two (ASL). and transfer the result into .Y. | |
DCBA | 0A | ASL | ||
DCBB | A8 | TAY | ||
DCBC | A9 02 | LDA #$02 | Store $02 into the buffer pointer BUFTAB,Y ($0099, Y) so it points to the first data byte in the buffer. | |
DCBE | 99 99 00 | STA $0099,Y | ||
DCC1 | B5 AE | LDA $AE,X | Load .A with the alternative-buffer number from BUF1,X ($AE,X), OR it with $80 to set the buffer-inactive bit, and store the result back in BUF1,X. | |
DCC3 | 09 80 | ORA #$80 | ||
DCC5 | 95 AE | STA $AE,X | ||
DCC7 | 0A | ASL | Multiply the buffer number (in .A) by two (ASL) and transfer the result to .Y. | |
DCC8 | A8 | TAY | ||
DCC9 | A9 02 | LDA #$02 | Store $02 into the buffer pointer BUFTAB,Y ($0099, Y) so it points to the first data byte in the buffer. | |
DCCB | 99 99 00 | STA $0099,Y | ||
DCCE | A9 00 | LDA #$00 | Zero the lo and hi bytes of the number of blocks written, NBKL,X ($B5,X) and NBKH,X ($BB,X) . | |
DCD0 | 95 B5 | STA $B5,X | ||
DCD2 | 95 BB | STA $BB,X | ||
DCD4 | A9 00 | LDA #$00 | Zero the last data byte LSTCHR,X ($0244) ,X. | |
DCD6 | 9D 44 02 | STA $0244,X | ||
DCD9 | 60 | RTS | Terminate routine with an RTS. | |
Open write channel with two buffers |
||||
OPNWCH | DCDA | 20 A9 F1 | JSR $F1A9 | JSR to INTTS ($F1A9) to get the first track and sector. |
DCDD | A9 01 | LDA #$01 | Load .A with $01 and JSR to GETWCH ($D1DF) to get one buffer for writing. | |
DCDF | 20 DF D1 | JSR $D1DF | ||
DCE2 | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0) to set up header image. | |
DCE5 | 20 B6 DC | JSR $DCB6 | JSR to INITP ($DCB6) to set up pointers. | |
DCE8 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DCEA | AD 4A 02 | LDA $024A | Load .A with the file type from TYPE ($024A) and save it onto the stack. | |
DCED | 48 | PHA | ||
DCEE | 0A | ASL | Multiply the file type in .A by two (ASL). OR it with the drive number from DRVNUM ($7F). and store the result as the file type in FILTYP,X ($EC,X). | |
DCEF | 05 7F | ORA $7F | ||
DCF1 | 95 EC | STA $EC,X | ||
DCF3 | 68 | PLA | Pull the original file type off the stack and if this is a relative file (type = $04), branch to OW10. | |
DCF4 | C9 04 | CMP #$04 | ||
DCF6 | F0 05 | BEQ $DCFD | ||
DCF8 | A9 01 | LDA #$01 | Since this is not a relative file, set channel status, CHNRDY,X ($F2,X) to $01 (active listener) . | |
DCFA | 95 F2 | STA $F2,X | ||
DCFC | 60 | RTS | Terminate routine with an RTS. | |
OW10 | DCFD | A4 83 | LDY $83 | Load .Y with the secondary address from SA ($83) . |
DCFF | B9 2B 02 | LDA $022B,Y | Load .A with the buffer type from LINTAB,Y ($022B,Y). AND it with $3F to mask off higher order bits, OR it with $40 to flag this as a READ/WRITE file, and store the result back in LINTAB,Y. | |
DD02 | 29 3F | AND #$3F | ||
DD04 | 09 40 | ORA #$40 | ||
DD06 | 99 2B 02 | STA $022B,Y | ||
DD09 | AD 58 02 | LDA $0258 | Copy record size from REC ($0258) into RS,X ($C7,X) . | |
DD0C | 95 C7 | STA $C7,X | ||
DD0E | 20 8E D2 | JSR $D28E | JSR to GETBUF ($D28E) to get a new buffer for storing the side sectors. If a buffer is available, branch to OW20 | |
DD11 | 10 03 | BPL $DD16 | ||
DD13 | 4C 0F D2 | JMP $D20F | No buffer available so abort with a JMP to GBERR ($D20F) . | |
OW20 | DD16 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . |
DD18 | 95 CD | STA $CD,X | Store the new side sector buffer number into SS,X ($CD,X) . | |
DD1A | 20 C1 DE | JSR $DEC1 | JSR to CLRBUF ($DEC1) to clear the side sector buffer. | |
DD1D | 20 1E F1 | JSR $F11E | JSR to NXTTS ($F11E) to find the next- available track and sector. | |
DD20 | A5 80 | LDA $80 | Copy the new track link from TRACK ($80) to TRKSS ($0259) . | |
DD22 | 8D 59 02 | STA $0259 | ||
DD25 | A5 81 | LDA $81 | Copy the new sector link from SECTOR ($81) to SECSS ($025A) . | |
DD27 | 8D 5A 02 | STA $025A | ||
DD2A | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DD2C | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X) . | |
DD2E | 20 D3 D6 | JSR $D6D3 | JSR to SETH ($D6D3) to set up the header | |
DD31 | A9 00 | LDA #$00 | Load .A with $00 and JSR to SETSSP ($DEE9) to set the buffer pointers using the current SS pointer (in .A) | |
DD33 | 20 E9 DE | JSR $DEE9 | ||
DD36 | A9 00 | LDA #$00 | Load .A with $00 and JSR to PUTSS ($DD8D) to set a null side sector link. | |
DD38 | 20 8D DD | JSR $DD8D | ||
DD3B | A9 11 | LDA #$11 | Load .A with $11 (the side sector offset plus 1) and JSR to PUTSS ($DD8D) to set the last character. | |
DD3D | 20 8D DD | JSR $DD8D | ||
DD40 | A9 00 | LDA #$00 | Load .A with $00 and JSR to PUTSS ($DD8D) to set this side sector number. | |
DD42 | 20 8D DD | JSR $DD8D | ||
DD45 | AD 58 02 | LDA $0258 | Load .A with the record size from REC ($0258) and JSR to PUTSS ($DD8D) to set the record size. | |
DD48 | 20 8D DD | JSR $DD8D | ||
DD4B | A5 80 | LDA $80 | Load .A with the file track link from TRACK ($80) and JSR to PUTSS ($DD8D) to set the track link. | |
DD4D | 20 8D DD | JSR $DD8D | ||
DD50 | A5 81 | LDA $81 | Load .A with the file sector link from SECTOR ($81) and JSR to PUTSS ($DD8D) to set the sector link. | |
DD52 | 20 8D DD | JSR $DD8D | ||
DD55 | A9 10 | LDA #$10 | Load .A with the side sector offset ($10) and JSR to PUTSS ($DD8D) to set the side sector offset. | |
DD57 | 20 E9 DE | JSR $DEE9 | ||
DD5A | 20 3E DE | JSR $DE3E | JSR to GETHDR ($DE3E) to get the track and sector of the first side sector. | |
DD5D | A5 80 | LDA $80 | Load .A with the SS track link from TRACK ($80) and JSR to PUTSS ($DD8D) to set the SS track link. | |
DD5F | 20 8D DD | JSR $DD8D | ||
DD62 | A5 81 | LDA $81 | Load .A with the SS sector link from SECTOR ($81) and JSR to PUTSS ($DD8D) to set the SS sector link. | |
DD64 | 20 8D DD | JSR $DD8D | ||
DD67 | 20 6C DE | JSR $DE6C | JSF to WRTSS ($DE6C) to write out the side sector block. | |
DD6A | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the write job to be completed. | |
DD6D | A9 02 | LDA #$02 | Load .A with $02 and JSR to SETPNT ($D4C8) to set the pointer into the data buffer to the start of the data. | |
DD6F | 20 C8 D4 | JSR $D4C8 | ||
DD72 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DD74 | 38 | SEC | Set the carry flag, load .A with $00, subtract the record size from RS,X ($C7,X), and store the result in NR,X ($C1,X) to set NR for a null buffer. | |
DD75 | A9 00 | LDA #$00 | ||
DD77 | F5 C7 | SBC $C7,X | ||
DD79 | 95 C1 | STA $C1,X | ||
DD7B | 20 E2 E2 | JSR $E2E2 | JSR to NULBUF ($E2E2) to set null records in the active buffer. | |
DD7E | 20 19 DE | JSR $DE19 | JSR to NULLNK ($DE19) to set track link to $00 and sector link to last non-zero character. | |
DD81 | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write out the null record block. | |
DD84 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the write job to be completed. | |
DD87 | 20 F4 EE | JSR $EEF4 | JSR to MAPOUT ($EEF4) to write out the BAM. | |
DD8A | 4C 98 DC | JMP $DC98 | JMP to OROW ($DC98) finish opening the channel . | |
Put byte into the side sector |
||||
PUTSS | DD8D | 48 | PHA | Push byte in .A cnto the stack. |
DD8E | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DD90 | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X) . | |
DD92 | 4C FD CF | JMP $CFFD | JMP to PUTB1 ($CFFD) . | |
SCFLG | DD95 | 90 06 | BCC $DD9D | Set/Clear flag: If carry flag clear, branch to CLRFLG |
SETFLG | DD97 | A6 82 | LDX $82 | Set flag: Load .X with the active buffer number from LINDX ($82) . |
DD99 | 15 EC | ORA $EC,X | OR the byte in .A with the file type in FILTYP,X ($EC,X) . | |
DD9B | D0 06 | BNE $DDA3 | If result is not $00, branch to CLRF10. | |
CLRFLG | DD9D | A6 82 | LDX $82 | Clear flag: Load .X with the active buffer number from LINDX ($82) . |
DD9F | 49 FF | EOR #$FF | EOR the byte in .A with $FF to flip all the bits. | |
DDA1 | 35 EC | AND $EC,X | AND the byte in .A with the file type in FILTYP,X ($EC,X) . | |
CLRF10 | DDA3 | 95 EC | STA $EC,X | Store the result in .A, as the new file type in FILTYP,X ($EC,X). |
DDA5 | 60 | RTS | Terminate routine with an RTS. | |
Test flag |
||||
TSTFLG | DDA6 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . |
DDA8 | 35 EC | AND $EC,X | AND the byte in .A with the file type in FILTYP,X ($EC,X) . | |
DDAA | 60 | RTS | Terminate routine with an RTS. | |
Test if this is a write job |
||||
TSTWRT | DDAB | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . |
DDAE | AA | TAX | Transfer the buffer number to .X. | |
DDAF | BD 5B 02 | LDA $025B,X | Load .A with the last job code from LSTJOB,X ($025B). AND the job code with $F0 to mask off the drive bits, and compare the result with $90 (write job code). This sets the Z flag if this is a write job. | |
DDB2 | 29 F0 | AND #$F0 | ||
DDB4 | C9 90 | CMP #$90 | ||
DDB6 | 60 | RTS | Terminate routine with an RTS. | |
Test for active files in LINDX tables
|
||||
TSTCHN | DDB7 | A2 00 | LDX #$00 | Load .X with $00 (secondary address) |
TSTC20 | DDB9 | 86 71 | STX $71 | Save .X value into TEMP + 2 ($71) . |
DDBB | BD 2B 02 | LDA $022B,X | Load .A with the buffer number for this secondary address from LINTAB,X (022B,X) If the buffer number is NOT $FF, branch to TSTC40 for further testing. | |
DDBE | C9 FF | CMP #$FF | ||
DDC0 | D0 08 | BNE $DDCA | ||
TSTC30 | DDC2 | A6 71 | LDX $71 | Restore .X value from TEMP+2 ($71) and increment it by 1. If the resulting .X value is less than $10 (the maximum sec. address - 2), loop back to TSTC20. |
DDC4 | E8 | INX | ||
DDC5 | E0 10 | CPX #$10 | ||
DDC7 | 90 F0 | BCC $DDB9 | ||
TSTRTS | DDC9 | 60 | RTS | Terminate routine with an RTS. |
TSTC40 | DDCA | 86 71 | STX $71 | Save .X value into TEMP+2 ($71) . |
DDCC | 29 3F | AND #$3F | AND the buffer number in .A with $3F to mask off the higher order bits and transfer the result into .Y. | |
DDCE | A8 | TAY | ||
DDCF | B9 EC 00 | LDA $00EC,Y | Load .A with the file type for this secondary address from FILTYP,Y ($EC,Y) , AND it with $01 to mask off the non-drive bits, and store the result in TEMP+1 ($70) . | |
DDD2 | 29 01 | AND #$01 | ||
DDD4 | 85 70 | STA $70 | ||
DDD6 | AE 53 02 | LDX $0253 | Load .X with the index entry found from ENTFND ($0253) . | |
DDD9 | B5 E2 | LDA $E2,X | Load .A with the drive number for this secondary address from FILDRV f X ($E2,X), AND it with $01 to mask off the non-drive bits, and compare the result with the drive number in TEMP + 1 ($70) . If the drives do not match, branch to TSTC30. | |
DDDB | 29 01 | AND #$01 | ||
DDDD | C5 70 | CMP $70 | ||
DDDF | D0 E1 | BNE $DDC2 | ||
DDE1 | B9 60 02 | LDA $0260,Y | Drive numbers match, now check if the directory entries match by comparing the entry sector in DSEC. Y ($026C , Y) with the one in ENTSEC,X ($D8,X). If they do not match, branch to TSTC30. | |
DDE4 | D5 D8 | CMP $D8,X | ||
DDE6 | D0 DA | BNE $DDC2 | ||
DDE8 | B9 66 02 | LDA $0266,Y | Drive numbers are match, now check if the directory entries match by comparing the entry index in DIND,Y ($0266, Y) with the one in ENTIND,X ($DD,X). If they do not match, branch to TSTC30. | |
DDEB | D5 DD | CMP $DD,X | ||
DDED | D0 D3 | BNE $DDC2 | ||
DDEF | 18 | CLC | Clear the carry flag to indicate that all tests passed and active file found. | |
DDF0 | 60 | RTS | Terminate routine with an RTS. | |
Write out buffer if dirty
|
||||
SCRUB | DDF1 | 20 9E DF | JSR $DF9E | JSR to GAFLGS ($DF9E) to get active buffer number and set in LBUSED. |
DDF4 | 50 06 | BVC $DDFC | If V flag not set, buffer is not dirty so branch to SCR1 . | |
DDF6 | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write out. the buffer to disk. | |
DDF9 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the job to be completed. | |
SCR1 | DDFC | 60 | RTS | Terminate routine with an RTS. |
Put TRACK and SECTOR into header |
||||
SETLNK | DDFD | 20 2B DE | JSR $DE2B | JSR to SETOO ($DE2B) to set up pointer to header. |
DE00 | A5 80 | LDA $80 | ||
DE02 | 91 94 | STA ($94),Y | Move desired track from TRACK ($80) to (DIRBUF) ,Y; ($94), Y. Increment .Y | |
DE04 | C8 | INY | ||
DE05 | A5 81 | LDA $81 | Move desired sector from SECTOR ($81) to (DIRBUF) ,Y; ($94) ,Y. | |
DE07 | 91 94 | STA ($94),Y | ||
DE09 | 4C 05 E1 | JMP $E105 | Terminate routine with a JMP to SDIRTY ($E105) to flag the buffer as dirty. | |
Set TRACK & SECTOR from link in buffer |
||||
GETLNK | DE0C | 20 2B DE | JSR $DE2B | JSR to SETOO ($DE2B) to set up pointer to header. |
DE0F | B1 94 | LDA ($94),Y | Move track link from (DIRBUF) ,Y; ( $94) ,Y to TRACK ($80). Increment .Y. | |
DE11 | 85 80 | STA $80 | ||
DE13 | C8 | INY | ||
DE14 | B1 94 | LDA ($94),Y | Move sector link from (DJRBUF),Y ($94) ,Y to SECTOR ($80) . | |
DE16 | 85 81 | STA $81 | ||
DE18 | 60 | RTS | Terminate routine with an RTS. | |
Set track link to $00 and sector link to the last non-zero character in buffer |
||||
NULLNK | DE19 | 20 2B DE | JSR $DE2B | JSR to SETOO ($DE2B) to set up pointer to header. |
DE1C | A9 00 | LDA #$00 | Store $00 as track link in (DIRBUF) ,Y ($94) ,Y. Increment .Y. | |
DE1E | 91 94 | STA ($94),Y | ||
DE20 | C8 | INY | ||
DE21 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DE23 | B5 C1 | LDA $C1,X | Load .A with the pointer into the data buffer from NR,X ($C1,X), decrement it by 1, and store the result as the sector link in (DIRBUF) ,Y; ($94) ,Y. | |
DE25 | AA | TAX | ||
DE26 | CA | DEX | ||
DE27 | 8A | TXA | ||
DE28 | 91 94 | STA ($94),Y | ||
DE2A | 60 | RTS | Terminate routine with an RTS. | |
Set up pointer to active buffer |
||||
SET00 | DE2B | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . |
DE2E | 0A | ASL | Multiply the buffer number (in .A) by two (ASL) and transfer the result to .X. | |
DE2F | AA | TAX | ||
DE30 | B5 9A | LDA $9A,X | Move the hi byte of the buffer pointer from BUFTAB+1,X ($9A,X) to DIRBUF+1 ( $95 ) | |
DE32 | 85 95 | STA $95 | ||
DE34 | A9 00 | LDA #$00 | Store $00 as the lo byte of the buffer pointer in DIRBUF ($94) . | |
DE36 | 85 94 | STA $94 | ||
DE38 | A0 00 | LDY #$00 | Zero .Y and exit routine with an RTS. | |
DE3A | 60 | RTS | ||
Set TRACK & SECTOR from header |
||||
CURBLK | DE3B | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. |
GETHDR | DE3E | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . |
DE41 | 85 F9 | STA $F9 | Store the buffer number in JOBNUM ($F9) | |
DE43 | 0A | ASL | Multiply the buffer number (in .A) by two (ASL) and transfer the result to .Y. | |
DE44 | A8 | TAY | ||
DE45 | B9 06 00 | LDA $0006,Y | Move the track number from the header table, HDRS,X ($0006, Y) to TRACK ($80). | |
DE48 | 85 80 | STA $80 | ||
DE4A | B9 07 00 | LDA $0007,Y | Move the sector number from the header table, HDRS+1,X($0007,Y) to SECTOR($81). | |
DE4D | 85 81 | STA $81 | ||
DE4F | 60 | RTS | Terminate routine with an RTS. | |
Do read and write jobs |
||||
WRTAB | DE50 | A9 90 | LDA #$90 | Store $90 (write job code) in CMD($024D) and branch to SJ10 (always) . |
DE52 | 8D 4D 02 | STA $024D | ||
DE55 | D0 28 | BNE $DE7F | ||
RDAB | DE57 | A9 80 | LDA #$80 | Store $80 (read job code) in CMD($024D) and branch to SJ10 (always) . |
DE59 | 8D 4D 02 | STA $024D | ||
DE5C | D0 21 | BNE $DE7F | ||
WRTOUT | DE5E | A9 90 | LDA #$90 | Store $90 (write job code) in CMD($024D) and branch to SJ20 (always) . |
DE60 | 8D 4D 02 | STA $024D | ||
DE63 | D0 26 | BNE $DE8B | ||
RDIN | DE65 | A9 80 | LDA #$80 | Store $80 (read job code) in CMD($024D) and branch to SJ20 (always) . |
DE67 | 8D 4D 02 | STA $024D | ||
DE6A | D0 1F | BNE $DE8B | ||
WRTSS | DE6C | A9 90 | LDA #$90 | Store $90 (write job code) in CMD($024D) and branch to RDS5 (always) . |
DE6E | 8D 4D 02 | STA $024D | ||
DE71 | D0 02 | BNE $DE75 | ||
RDSS | DE73 | A9 80 | LDA #$80 | Load .A with $80 (read job code) |
RDS5 | DE75 | 8D 4D 02 | STA $024D | Store job code (in .A) into CMD($024D). |
DE78 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DE7A | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X) and tranfer it to .X. If the SS buffer number < 127, branch to SJ30. | |
DE7C | AA | TAX | ||
DE7D | 10 13 | BPL $DE92 | ||
SJ10 | DE7F | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0) to set header from TRACK and SECTOR. |
DE82 | 20 93 DF | JSR $DF93 | JSR to GETACT to get the active buffer number (returned in .A) . | |
DE85 | AA | TAX | Transfer the buffer number to .X. | |
DE86 | A5 7F | LDA $7F | Copy the drive number from DRVNUM ($7F) to LSTJOB,X ($025B,X) . | |
DE88 | 9D 5B 02 | STA $025B,X | ||
SJ20 | DE8B | 20 15 E1 | JSR $E115 | JSR to CDIRTY ($E115) to clear the dirty buffer flag. |
DE8E | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
DE91 | AA | TAX | Transfer the buffer number to .X. | |
DE92 | 4C 06 D5 | JMP $D506 | Continue routine with JMP to SETLJB ($D506) to set last used buffer. | |
Set TRACK & SECTOR from link in buffer |
||||
RDLNK | DE95 | A9 00 | LDA #$00 | Load .A with $00 and JSR to SETPNT ($D4C8) to set the buffer pointer to the first byte in the buffer (track link) . |
DE97 | 20 C8 D4 | JSR $D4C8 | ||
DE9A | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read the track link. Store the link in TRACK ($80) . | |
DE9D | 85 80 | STA $80 | ||
DE9F | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read the sector link. Store the link in SECTOR ($81) . | |
DEA2 | 85 81 | STA $81 | ||
DEA4 | 60 | RTS | Terminate routine with an RTS. | |
Move bytes from one buffer to another
|
||||
B0TOB0 | DEA5 | 48 | PHA | Save number of bytes to move (in .A) onto the stack. |
DEA6 | A9 00 | LDA #$00 | Zero TEMP ($6F) and TEMP+2 ($71). | |
DEA8 | 85 6F | STA $6F | ||
DEAA | 85 71 | STA $71 | ||
DEAC | B9 E0 FE | LDA $FEE0,Y | Move the hi byte of the from buffer pointer from BUFIND,Y ($FEE0,Y) to TEMP+1 ($70) . | |
DEAF | 85 70 | STA $70 | ||
DEB1 | BD E0 FE | LDA $FEE0,X | Move the hi byte of the to buffer pointer from BUFIND,X ($FEE0,X) to TEMP+3 ($72) . | |
DEB4 | 85 72 | STA $72 | ||
B02 | DEB6 | 68 | PLA | Pull the number-of-bytes-to-move from the stack, transfer it into .Y, and decrement .Y by 1 (0th byte is #1) . |
DEB7 | A8 | TAY | ||
DEB8 | 88 | DEY | ||
DEB9 | B1 6F | LDA ($6F),Y | Loop using. Y as a count-down index to transfer bytes from (TEMP)Y to (TEMP+2) Y | |
DEBB | 91 71 | STA ($71),Y | ||
DEBD | 88 | DEY | ||
DEBE | 10 F9 | BPL $DEB9 | ||
DEC0 | 60 | RTS | Terminate routine with an RTS. | |
Clear buffer: (buffer # in .A) |
||||
CLRBUF | DEC1 | A8 | TAY | Transfer buffer number from .A to .Y. |
DEC2 | B9 E0 FE | LDA $FEE0,Y | Move the hi byte of the from buffer pointer from BUFIND,Y ($FEE0,Y) to TEMP + 1 ($70) . | |
DEC5 | 85 70 | STA $70 | ||
DEC7 | A9 00 | LDA #$00 | Zero TEMP ($6F) and .Y | |
DEC9 | 85 6F | STA $6F | ||
DECB | A8 | TAY | ||
CB10 | DECC | 91 6F | STA ($6F),Y | Loop to fill buffer with $00 's. |
DECE | C8 | INY | ||
DECF | D0 FB | BNE $DECC | ||
DED1 | 60 | RTS | Terminate routine with an RTS. | |
Set side sector pointer to $00 |
||||
SSSET | DED2 | A9 00 | LDA #$00 | Zero .A and JSR to SSDIR ($DEDC) to set DIRBUF with current SS pointer. |
DED4 | 20 DC DE | JSR $DEDC | ||
DED7 | A0 02 | LDY #$02 | Load .Y with $02. Load .A with the side sector pointer from (DIRBUF) ,Y; ($94) ,Y. | |
DED9 | B1 94 | LDA ($94),Y | ||
DEDB | 60 | RTS | Terminate routine with an RTS. | |
Use SS pointer to set DIRBUFOn entry: .A = lo byte |
||||
SSDIR | DEDC | 85 94 | STA $94 | Store lo byte (in .A) into DIRBUF ($94) |
DEDE | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . | |
DEE0 | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X) . | |
DEE2 | AA | TAX | Transfer SS buffer number to .X. | |
DEE3 | BD E0 FE | LDA $FEE0,X | Copy hi byte of buffer pointer from BUFIND ($FEE0) toDIRBUF+1 ($95). | |
DEE6 | 85 95 | STA $95 | ||
DEE8 | 60 | RTS | Terminate routine with an RTS. | |
Use SS pointer to set DIRBUF & BUFTABOn entry: .A = lo byte |
||||
SETSSP | DEE9 | 48 | PHA | Save lo byte (in .A) onto the stack. |
DEEA | 20 DC DE | JSR $DEDC | JSR to SSDIR ($DEDC) to set DIRBUF from current SS pointer. | |
DEED | 48 | PHA | On return, .A contains the hi byte of the SS buffer pointer. Save the hi byte onto the stack. | |
DEEE | 8A | TXA | Transfer the SS buffer number from .X to .A, multiply it by two (ASL). and transfer it back into .X. | |
DEEF | 0A | ASL | ||
DEF0 | AA | TAX | ||
DEF1 | 68 | PLA | Pull hi byte of SS buffer pointer off the stack and store it in BUFTAB+1,X ($9A,X) . | |
DEF2 | 95 9A | STA $9A,X | ||
DEF4 | 68 | PLA | Pull lo byte of SS buffer pointer off the stack and store it in BUFTAB ,X ($99, X) . | |
DEF5 | 95 99 | STA $99,X | ||
DEF7 | 60 | RTS | Terminate routine with an RTS. | |
Use SSNUM & SSIND to set SS & BUFTAB
|
||||
SSPOS | DEF8 | 20 66 DF | JSR $DF66 | JSR to SSTEST ($DF66) to test if SSNUM & SSIND are resident and within range. |
DEFB | 30 0E | BMI $DF0B | If N flag set, out of range so branch to SSP10. | |
DEFD | 50 13 | BVC $DF12 | If V flag clear, it is in residence so branch to SSP20. | |
DEFF | A6 82 | LDX $82 | Since V flag set, maybe in range and maybe not. Do another test: Load .X with the active buffer number from LINDX ($82) . | |
DF01 | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X). | |
DF03 | 20 1B DF | JSR $DF1B | JSR to IBRD ($DF1B) to read in the SS. | |
DF06 | 20 66 DF | JSR $DF66 | JSR to SSTEST ($DF66) to test again. | |
DF09 | 10 07 | BPL $DF12 | If N flag clear, it is in range so branch to SSP20. | |
SSP10 | DF0B | 20 CB E1 | JSR $E1CB | Out of range so JSR to SSEND ($E1CB) to set SS & BUFTAB to end of last record. |
DF0E | 2C CE FE | BIT $FECE | BIT with ER1 ($FECE) to set flags and terminate routine with an RTS. | |
DF11 | 60 | RTS | ||
SSP20 | DF12 | A5 D6 | LDA $D6 | Load .A with the SS pointer from SSIND ($D6) . |
DF14 | 20 E9 DE | JSR $DEE9 | JSR to SETSSP ($DEE9) to set DIRBUF and BUFTAB. | |
DF17 | 2C CD FE | BIT $FECD | BIT with ERO ($FECD) to set flags and terminate routine with an RTS. | |
DF1A | 60 | RTS | ||
Indirect block read/write:
|
||||
IBRD | DF1B | 85 F9 | STA $F9 | Store buffer number (.A) in JOBNUM ($F9) |
DF1D | A9 80 | LDA #$80 | Load .A with $80 (read job code) and branch to IBOP. | |
DF1F | D0 04 | BNE $DF25 | ||
IBWT | DF21 | 85 F9 | STA $F9 | Store buffer number (.A) in JOBNUM ($F9) |
DF23 | A9 90 | LDA #$90 | Load .A with $90 (write job code) | |
IBOP | DF25 | 48 | PHA | Push the job code onto the stack. |
DF26 | B5 EC | LDA $EC,X | Load .A with the file's drive number from FILTYP,X ($EC,X), AND it with $01 to mask off the non-drive bits, and use it to set the drive, DRVNUM ($7F) | |
DF28 | 29 01 | AND #$01 | ||
DF2A | 85 7F | STA $7F | ||
DF2C | 68 | PLA | Pull the job code off the stack, OR it with the drive number in DRVNUM ($7F) , and store the result in CMD ($024D) . | |
DF2D | 05 7F | ORA $7F | ||
DF2F | 8D 4D 02 | STA $024D | ||
DF32 | B1 94 | LDA ($94),Y | Move the track number from (DIRBUF) ,Y ($94), Y to TRACK ($80). Increment .Y | |
DF34 | 85 80 | STA $80 | ||
DF36 | C8 | INY | ||
DF37 | B1 94 | LDA ($94),Y | Move the sector number from (DIRBUF) ,Y ($94) ,Y to SECTOR ($81) . | |
DF39 | 85 81 | STA $81 | ||
DF3B | A5 F9 | LDA $F9 | Load .A with the buffer number from JOBNUM ($F9) and JSR to SETH ($D6D3) to set up the header. | |
DF3D | 20 D3 D6 | JSR $D6D3 | ||
DF40 | A6 F9 | LDX $F9 | Load .X with the buffer number from JOBNUM ($F9) and JMP to DOIT2 ($D593) to do the job. | |
DF42 | 4C 93 D5 | JMP $D593 | ||
Get side sector pointers |
||||
GSSPNT | DF45 | A6 82 | LDX $82 | Load .X with the active buffer number from LINDX ($82) . |
DF47 | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X) | |
DF49 | 4C EB D4 | JMP $D4EB | JMP to SETDIR($D4EB) to set the DIRBUF pointers . | |
Calculate side sectors |
||||
SCAL1 | DF4C | A9 78 | LDA #$78 | Load .A with $78, the number of side sector pointers in a buffer. |
DF4E | 20 5C DF | JSR $DF5C | JSR to ADDT12 ($DF5C) to add the number of side sectors needed * 120. | |
SSCALC | DF51 | CA | DEX | Decrement .X. If .X >= $00, branch to SCAL1. |
DF52 | 10 F8 | BPL $DF4C | ||
DF54 | A5 72 | LDA $72 | Load .A with the number of SS indices needed from T3($72) and multiply it by 2 (ASL) since two bytes (track & sec) are needed for each index, | |
DF56 | 4A | LSR | ||
DF57 | 20 5C DF | JSR $DF5C | JSR to ADDT12 to add .A to T1 & T2. | |
DF5A | A5 73 | LDA $73 | Load .A with the number of SS blocks needed from T4($73) | |
ADDT12 | DF5C | 18 | CLC | Clear the carry flag. |
DF5D | 65 70 | ADC $70 | Add the contents of Tl ($70) to the contents of the accumulator and store the result back in Tl ($70). | |
DF5F | 85 70 | STA $70 | ||
DF61 | 90 02 | BCC $DF65 | If carry is clear, branch to ADDRTS. | |
DF63 | E6 71 | INC $71 | Increment the value in T2 ($71) . | |
ADDRTS | DF65 | 60 | RTS | Terminate routine with an RTS. |
Test SSNUM & SSIND for range & residenceFlag meanings on exit:
|
||||
SSTEST | DF66 | 20 D2 DE | JSR $DED2 | JSR to SSSET ($DED2) to set the pointer to $00 and get the SS number (in .A) . |
DF69 | C5 D5 | CMP $D5 | Compare the SS number in .A with the one in SSNUM ($D5). If they are not equal, branch to ST20. | |
DF6B | D0 0E | BNE $DF7B | ||
DF6D | A4 D6 | LDY $D6 | Load .Y with the pointer into the SS buffer from SSIND ($D6) | |
DF6F | B1 94 | LDA ($94),Y | Load .A from (DIRBUF) ,Y; ($94), Y. If this value is $00, the proper side sector is not present so branch to ST10. | |
DF71 | F0 04 | BEQ $DF77 | ||
DF73 | 2C CD FE | BIT $FECD | BIT ERO ($FECD) to clear the N and V flags. All OK so exit with an RTS. | |
DF76 | 60 | RTS | ||
ST10 | DF77 | 2C CF FE | BIT $FECF | Definitely out of range so BIT with E2 ($FECF) and exit with an RTS. |
DF7A | 60 | RTS | ||
ST20 | DF7B | A5 D5 | LDA $D5 | Load .A with the SS number from SSNUM ($D5) and compare it with $06, the number of side sector links. If the value in SSNUM > $06, branch to ST30. |
DF7D | C9 06 | CMP #$06 | ||
DF7F | B0 0A | BCS $DF8B | ||
DF81 | 0A | ASL | Multiply the SS number in .A by 2 (ASL) and transfer the result into .Y. | |
DF82 | A8 | TAY | ||
DF83 | A9 04 | LDA #$04 | Load .A with $04, and store this value in DIRBUF ($94), lo byte of the pointer, | |
DF85 | 85 94 | STA $94 | ||
DF87 | B1 94 | LDA ($94),Y | Load .A with the value from (DIRBUF) ,Y ($94) ,Y. If thisvalue is not $00, branch to ST40. | |
DF89 | D0 04 | BNE $DF8F | ||
ST30 | DF8B | 2C D0 FE | BIT $FED0 | Way out of range so BIT with E3 ($FED0) and exit with an RTS. |
DF8E | 60 | RTS | ||
ST40 | DF8F | 2C CE FE | BIT $FECE | Not in residence and range is unknown so BIT with El ($FECE) and exit with RTS |
DF92 | 60 | RTS | ||
Get active buffer number
|
||||
GETACT | DF93 | A6 82 | LDX $82 | Load .X with the current buffer number from LINDX ($82) . |
DF95 | B5 A7 | LDA $A7,X | Load .A with the buffer number from BUF0,X ($A7,X). If bit 7 is not set, this buffer is active so branch to GA1 . | |
DF97 | 10 02 | BPL $DF9B | ||
DF99 | B5 AE | LDA $AE,X | Load .A with the buffer number from BUF1,X ($AE,X) . | |
GA1 | DF9B | 29 BF | AND #$BF | AND the buffer number with $BF to strip the dirty bit. |
DF9D | 60 | RTS | Terminate routine with an RTS. | |
Get active buffer & set LBUSED
|
||||
GAFLGS | DF9E | A6 82 | LDX $82 | Load .X with the current buffer number from LINDX ($82) . |
GA2 | DFA0 | 8E 57 02 | STX $0257 | Save buffer number into LBUSED ($0257) . |
DFA3 | B5 A7 | LDA $A7,X | Load .A with the buffer number from BUF0,X ($A7,X). If bit 7 is not set, this buffer is active so branch to GA3 . | |
DFA5 | 10 09 | BPL $DFB0 | ||
DFA7 | 8A | TXA | Transfer the buffer number from .X to .A, clear the carry flag, add $07 (the maximum number of channels + 1). and store the result in LBUSED ($0257) . | |
DFA8 | 18 | CLC | ||
DFA9 | 69 07 | ADC #$07 | ||
DFAB | 8D 57 02 | STA $0257 | ||
DFAE | B5 AE | LDA $AE,X | Load .A with the buffer number from BUF1,X ($AE,X) . | |
GA3 | DFB0 | 85 70 | STA $70 | Store the buffer number in Tl ($70) . |
DFB2 | 29 1F | AND #$1F | AND the buffer number with $1F and BIT the result with T1 ($70) to set the N and V flags. | |
DFB4 | 24 70 | BIT $70 | ||
DFB6 | 60 | RTS | Terminate routine with an RTS. | |
Get a channel's inactive buffer number
|
||||
GETINA | DFB7 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
DFB9 | B5 A7 | LDA $A7,X | Load .A with the buffer number from BUF0,X ($A7,X). If bit 7 is set, this buffer is inactive so branch to GI10. | |
DFBB | 30 02 | BMI $DFBF | ||
DFBD | B5 AE | LDA $AE,X | Load .A with the buffer number from BUF1,X ($AE,X) . | |
GI10 | DFBF | C9 FF | CMP #$FF | Compare the buffer number with $FF to set the Z flag if inactive buffer found. |
DFC1 | 60 | RTS | Terminate routine with an RTS. | |
Set the inactive buffer's buffer numberOn entry: .A = buffer number |
||||
PUTINA | DFC2 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
DFC4 | 09 80 | ORA #$80 | OR the buffer number in .A with $80 to set the inactive buffer bit. | |
DFC6 | B4 A7 | LDY $A7,X | Load. Y with the buffer number from BUF0,X ($A7,X). If bit 7 is clear, the other buffer is the inactive one so branch to PI1. | |
DFC8 | 10 03 | BPL $DFCD | ||
DFCA | 95 A7 | STA $A7,X | This buffer is inactive so store new buffer number in BUF0,X ($A7,X). | |
DFCC | 60 | RTS | Exit with an RTS. | |
PI1 | DFCD | 95 AE | STA $AE,X | This buffer is inactive so store new buffer number in BUF1,X ($AE,X). |
DFCF | 60 | RTS | Exit with an RTS. | |
Set up next relative record |
||||
NXTREC | DFD0 | A9 20 | LDA #$20 | Load .A with $20 (overflow flag) and JSR to CLRFLG ($DD9D) to clear the record overflow flag. |
DFD2 | 20 9D DD | JSR $DD9D | ||
DFD5 | A9 80 | LDA #$80 | Load .A with $80 (last record flag) and JSR to TSTFLG ($DDA6) to test if we are out beyond the last record. If not, branch to NXTR40. | |
DFD7 | 20 A6 DD | JSR $DDA6 | ||
DFDA | D0 41 | BNE $E01D | ||
DFDC | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . | |
DFDE | F6 B5 | INC $B5,X | Increment the lo byte of the record counter in RECL,X ($B5,X). If the result is not $00, branch to NXTR15. | |
DFE0 | D0 02 | BNE $DFE4 | ||
DFE2 | F6 BB | INC $BB,X | Increment the hi byte of the record counter in RECH,X ($BB,X) . | |
NXTR15 | DFE4 | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . |
DFE6 | B5 C1 | LDA $C1,X | Load .A with the pointer to the next record from NR,X ($C1,X). | |
DFE8 | F0 2E | BEQ $E018 | If the next record pointer is $00. there is no next record so branch to NXTR45. | |
DFEA | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to get the buffer pointer. | |
DFED | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . | |
DFEF | D5 C1 | CMP $C1,X | Compare the buffer pointer in .A with the pointer in NR,X ($C1,X). If BT<NR then branch to NXTR20. | |
DFF1 | 90 03 | BCC $DFF6 | ||
DFF3 | 20 3C E0 | JSR $E03C | Not in this buffer, must be in the next- one so JSR to NRBUF ($E03C) to set up the next. one. | |
NXTR20 | DFF6 | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . |
DFF8 | B5 C1 | LDA $C1,X | Load .A with the pointer to the next record from NR,X ($C1,X). | |
DFFA | 20 C8 D4 | JSR $D4C8 | JSR to SETPNT ($D4C8) to advance to the next record. | |
DFFD | A1 99 | LDA ($99,X) | Load .A with the first byte of the record from (BUFTAB,X) ($99, X) . | |
DFFF | 85 85 | STA $85 | Save the first data byte into DATA ($85) | |
E001 | A9 20 | LDA #$20 | Load .A with $20 (overflow flag) and JSR to CLRFLG ($DD9D) to clear the record overflow flag. | |
E003 | 20 9D DD | JSR $DD9D | ||
E006 | 20 04 E3 | JSR $E304 | JSR to ADDNR ($E304) to advance the NR pointer. | |
NXOUT | E009 | 48 | PHA | Save the new value of NR (in .A) onto the stack. If the carry flag is clear, we have NOT crossed a block boundary so branch to NXTR30. |
E00A | 90 28 | BCC $E034 | ||
E00C | A9 00 | LDA #$00 | Load .A with $00 and JSR to DRDBYT ($D4F6) to read the track link of the data block. If the track link is not $00, this is not the last block so branch to NXTR30. | |
E00E | 20 F6 D4 | JSR $D4F6 | ||
E011 | D0 21 | BNE $E034 | ||
E013 | 68 | PLA | Pull the new NR value off the stack and compare it to $02. If it equals $02, branch to NXTR50 | |
E014 | C9 02 | CMP #$02 | ||
E016 | F0 12 | BEQ $E02A | ||
NXTR45 | E018 | A9 80 | LDA #$80 | Load .A with $80 (last record flag) and JSR to SETFLG ($DDD97) to set this flag. |
E01A | 20 97 DD | JSR $DD97 | ||
NXTR40 | E01D | 20 2F D1 | JSR $D12F | JSR to GETPRE ($D12F) to get pointers. |
E020 | B5 99 | LDA $99,X | Move the data byte from BUFTAB,X ($99, X) to LSTCHR ($0244. | |
E022 | 99 44 02 | STA $0244,Y | ||
E025 | A9 0D | LDA #$0D | Store $0D (carriage return) in DATA($85) | |
E027 | 85 85 | STA $85 | ||
E029 | 60 | RTS | Terminate routine with an RTS. | |
NXTR50 | E02A | 20 35 E0 | JSR $E035 | JSR to NXTR35 ($E035) to store NR value |
E02D | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82). Store $00 in NR,X ($C1,X). | |
E02F | A9 00 | LDA #$00 | ||
E031 | 95 C1 | STA $C1,X | ||
E033 | 60 | RTS | Terminate routine with an RTS. | |
NXTR30 | E034 | 68 | PLA | Pull the new NR value off the stack. |
NXTR35 | E035 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82). Store the byte in .A into NR,X ($C1,X) . |
E037 | 95 C1 | STA $C1,X | ||
E039 | 4C 6E E1 | JMP $E16E | Terminate routine with a JMP to SETLST ($E16E) to set. the pointer to the last character. | |
Set up next record in buffer |
||||
NRBUF | E03C | 20 D3 D1 | JSR $D1D3 | JSR to SETDRN ($D1D3) to set drive number to agree with the last job. |
E03F | 20 95 DE | JSR $DE95 | JSR to RDLNK ($DE95) to set TRACK and SECTOR from the track & sector link. | |
E042 | 20 9E DF | JSR $DF9E | JSR to GAFLGS ($DF9E) to test, if the current buffer is dirty (changed). If V flag clear, it is clean; branch to NRBU50 so we don't write it out. | |
E045 | 50 16 | BVC $E05D | ||
E047 | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write it out. | |
E04A | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. | |
E04D | A9 02 | LDA #$02 | Load .A with $02 and JSR to SETPNT ($D4C8) to set the pointer to point to the first data byte in the new sector. | |
E04F | 20 C8 D4 | JSR $D4C8 | ||
E052 | 20 AB DD | JSR $DDAB | JSR to TSTWRT ($DDAB) to test if the last job was a write. If it was not a write job, branch to NRBU20 ($E07B) since buffer is OK. | |
E055 | D0 24 | BNE $E07B | ||
E057 | 20 57 DE | JSR $DE57 | JSR to RDAB ($DE57) to read in needed buffer. | |
E05A | 4C 99 D5 | JMP $D599 | JSR to WATJOB ($D599) to wait for the read job to be completed. | |
NRBU50 | E05D | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. |
E060 | 20 AB DD | JSR $DDAB | JSR to TSTWRT ($DDAB) to test if the last job was a write. If it was not a write job, branch to NRBU70. | |
E063 | D0 06 | BNE $E06B | ||
E065 | 20 57 DE | JSR $DE57 | JSR to RDAB ($DE57) to read in needed buffer. | |
E068 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the read job to be completed. | |
NRBU70 | E06B | 20 95 DE | JSR $DE95 | JSR to RDLNK ($DE95) to set TRACK and SECTOR from the track & sector link. |
E06E | A5 80 | LDA $80 | Load .A with the track link from TRACK ($80). If track link is $00, this is the last block with no double buffering needed so branch to NRBU20. | |
E070 | F0 09 | BEQ $E07B | ||
E072 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. | |
E075 | 20 57 DE | JSR $DE57 | JSR to RDAB ($DE5E) to start a read job for the inactive buffer. | |
E078 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. | |
NRBU20 | E07B | 60 | RTS | Terminate routine with an RTS. |
Put relative record into buffer |
||||
RELPUT | E07C | 20 05 E1 | JSR $E105 | JSR to SDIRTY ($E105) to flag buffer as dirty (RAM version changed) . |
E07F | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get active buffer number (returned in .A) . | |
E082 | 0A | ASL | Multiply the buffer number (in .A) by two (ASL) and transfer the result to .X. | |
E083 | AA | TAX | ||
E084 | A5 85 | LDA $85 | Copy the data byte from DATA ($85) into the buffer at (BUFTAB,X) ($99, X). | |
E086 | 81 99 | STA ($99,X) | ||
E088 | B4 99 | LDY $99,X | Load .Y with the lo byte of the pointer BUFTAB,X and increment the pointer in . Y by 1. If the new pointer value is NOT $00, branch to RELP05. | |
E08A | C8 | INY | ||
E08B | D0 09 | BNE $E096 | ||
E08D | A4 82 | LDY $82 | Load .Y with the channel number from LINDX ($82) . | |
E08F | B9 C1 00 | LDA $00C1,Y | Load .A with the next record pointer from NR,Y. If this value is $00, branch to RELP0 7. | |
E092 | F0 0A | BEQ $E09E | ||
RELP06 | E094 | A0 02 | LDY #$02 | Load .Y with $02. |
RELP05 | E096 | 98 | TYA | Transfer the contents of .Y to .A. |
E097 | A4 82 | LDY $82 | Load .Y with the channel number from LINDX ($82). | |
E099 | D9 C1 00 | CMP $00C1,Y | Compare the contents of .A to NR,Y ($C1,Y) to test if NR = pointer. If they are not equal, NR is not a pointer so branch to RELP10 to set new pointer. | |
E09C | D0 05 | BNE $E0A3 | ||
RELP07 | E09E | A9 20 | LDA #$20 | Load .A with $20 (the overflow flag) and JMP to SETFLG ($DD9 7) to set the overflow flag and exit. |
E0A0 | 4C 97 DD | JMP $DD97 | ||
RELP10 | E0A3 | F6 99 | INC $99,X | Increment the lo byte of the pointer BUFTAB,X ($99, X). If the result is not $00, we don't need the next buffer so branch to RELP20. |
E0A5 | D0 03 | BNE $E0AA | ||
E0A7 | 20 3C E0 | JSR $E03C | JSR to NRBUF($E03C) to get next buffer. | |
RELP20 | E0AA | 60 | RTS | Terminate routine with an RTS. |
Write out relative records |
||||
WRTREL | E0AB | A9 A0 | LDA #$A0 | Load .A with $A0 (last record flag + overflow flag) and JSR to TSTFLG ($DDA6) to check for last record & overflow. |
E0AD | 20 A6 DD | JSR $DDA6 | ||
E0B0 | D0 27 | BNE $E0D9 | If Z flag clear, some flag is set so branch to WR50. | |
WR10 | E0B2 | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) and JSR to RELPUT ($E07C) to put the data into the buffer. |
E0B4 | 20 7C E0 | JSR $E07C | ||
WR20 | E0B7 | A5 F8 | LDA $F8 | Load .A with the EOIFLG ($F8). If it equals $00, an EOI was NOT sent so branch to WR40. |
E0B9 | F0 0D | BEQ $E0C8 | ||
E0BB | 60 | RTS | Terminate routine with an RTS. | |
WR30 | E0BC | A9 20 | LDA #$20 | Load .A with $20 (overflow flag) and JSR to TSTFLG ($DDA6) to test for an overflow error. |
E0BE | 20 A6 DD | JSR $DDA6 | ||
E0C1 | F0 05 | BEQ $E0C8 | If Z set, no error so branch to WR40. | |
E0C3 | A9 51 | LDA #$51 | Overflow error so load .A with $51 (recover flag) and store it in ERWORD ($026C) to flag the error. | |
E0C5 | 8D 6C 02 | STA $026C | ||
WR40 | E0C8 | 20 F3 E0 | JSR $E0F3 | JSR to CLREC ($E0F3) to clear the rest of the record. |
E0CB | 20 53 E1 | JSR $E153 | JSR to RD40 ($E153) to set up for the next record. | |
E0CE | AD 6C 02 | LDA $026C | Load .A from ERWORD ($026C). If it is $00, no errors so branch to WR45. | |
E0D1 | F0 03 | BEQ $E0D6 | ||
E0D3 | 4C C8 C1 | JMP $C1C8 | Abort with a JMP to CMDERR ($C1C8) | |
WR45 | E0D6 | 4C BC E6 | JMP $E6BC | Terminate with a JMP to OKERR ($E6BC) . |
WR50 | E0D9 | 29 80 | AND #$80 | AND the error flag in .A with $80 (the last record flag). If the result is not $00, the last record flag was set so branch to WR60 to add to file. |
E0DB | D0 05 | BNE $E0E2 | ||
E0DD | A5 F8 | LDA $F8 | Load .A with the EOIFLG ($F8). If this is $00, an EOI was not sent so branch to WR3 0. | |
E0DF | F0 DB | BEQ $E0BC | ||
WR51 | E0E1 | 60 | RTS | Terminate routine with an RTS. |
WR60 | E0E2 | A5 85 | LDA $85 | Load .A with the data byte from DATA ($85) and push it onto the stack. |
E0E4 | 48 | PHA | ||
E0E5 | 20 1C E3 | JSR $E31C | JSR to ADDREL ($E31C) to add to the relative file. | |
E0E8 | 68 | PLA | ||
E0E9 | 85 85 | STA $85 | Pull the data byte off the stack and put it back in DATA ($85). | |
E0EB | A9 80 | LDA #$80 | Load .A with $80 (last record flag) and JSR to CLRFLG ($DD9D) to clear the flag. | |
E0ED | 20 9D DD | JSR $DD9D | ||
E0F0 | 4C B2 E0 | JMP $E0B2 | JMP to WR10. | |
Clear rest of relative record |
||||
CLREC | E0F3 | A9 20 | LDA #$20 | Load .A with $20 (overflow flag) and JSR to TSTFLG ($DDA6) to test the flag. |
E0F5 | 20 A6 DD | JSR $DDA6 | ||
E0F8 | D0 0A | BNE $E104 | If Z flag not set, overflow has occured so branch to CLR10 to exit. | |
E0FA | A9 00 | LDA #$00 | Set DATA ($85) to $00 and JSR to RELPUT ($E07C) to put a null byte in the buffer | |
E0FC | 85 85 | STA $85 | ||
E0FE | 20 7C E0 | JSR $E07C | ||
E101 | 4C F3 E0 | JMP $E0F3 | Loop with a JMP to CLREC ($E0F3). | |
CLR10 | E104 | 60 | RTS | Terminate routine with an RTS. |
Set buffer dirty flag |
||||
SDIRTY | E105 | A9 40 | LDA #$40 | Load .A with $40 (dirty flag) . |
E107 | 20 97 DD | JSR $DD97 | JSR to SETFLG ($DD97) to set flag. | |
E10A | 20 9E DF | JSR $DF9E | JSR to GAFLGS ($DF9E) to get active buffer number in .A and set flags. | |
E10D | 09 40 | ORA #$40 | OR the contents of .A with $40 to set the dirty flag. | |
E10F | AE 57 02 | LDX $0257 | Load .X with the number of the last buffer used from LBUSED ($0257). | |
E112 | 95 A7 | STA $A7,X | Store the content of .A as the buffer number in BUF0,X ($A7,X). | |
E114 | 60 | RTS | Terminate routine with an RTS. | |
Clear buffer dirty flag |
||||
CDIRTY | E115 | 20 9E DF | JSR $DF9E | JSR to GAFLGS ($DF9E) to get active buffer number and set flags. |
E118 | 29 BF | AND #$BF | AND the contents of .A with $BF to clear the dirty flag. | |
E11A | AE 57 02 | LDX $0257 | Load .X with the number of the last. buffer used from LBUSED ($0257). | |
E11D | 95 A7 | STA $A7,X | Store the content of .A as the buffer number in BUF0,X ($A7,X). | |
E11F | 60 | RTS | Terminate routine with an RTS. | |
Read relative record |
||||
RDREL | E120 | A9 80 | LDA #$80 | Load .A with $80 (last record flag) and JSR to TSTFLG ($DDA6) to test the flag. |
E122 | 20 A6 DD | JSR $DDA6 | ||
E125 | D0 37 | BNE $E15E | If Z flag not set, last, record error has occured so branch to RD05. | |
RD10 | E127 | 20 2F D1 | JSR $D12F | JSR to GETPRE ($D12F) to set pointers to existing buffer. |
E12A | B5 99 | LDA $99,X | Load .A with the lo byte of the buffer pointer from BUFTAB,X ($99, X). | |
E12C | D9 44 02 | CMP $0244,Y | Compare this value to the contents of LSTCHR,Y ($0244). If they are equal, branch to RD40 because we want the next record not the last one. | |
E12F | F0 22 | BEQ $E153 | ||
E131 | F6 99 | INC $99,X | Increment the buffer pointer in BUFTAB,X ($99, X). If the result is not equal to $00, we don't need the next buffer so branch to RD20. | |
E133 | D0 06 | BNE $E13B | ||
E135 | 20 3C E0 | JSR $E03C | JSR to NRBUF ($E03C) to read in the next buffer of relative records. | |
RD15 | E138 | 20 2F D1 | JSR $D12F | JSR to GETPRE ($D12F) to set pointers to existing buffer. |
RD20 | E13B | A1 99 | LDA ($99,X) | Load .A with the data byte from (BUFTAB,X) ; ($99, X) . |
RD25 | E13D | 99 3E 02 | STA $023E,Y | Store the data byte in CHNDAT, Y ($023E, Y) |
E140 | A9 89 | LDA #$89 | Load .A with $89 (random access - ready) and store this as the channel status in CHNRDY,Y ($F2,Y) . | |
E142 | 99 F2 00 | STA $00F2,Y | ||
E145 | B5 99 | LDA $99,X | Load the pointer from BUFTAB,X ($99, Y) and compare it to the pointer to the last character in the record from LSTCHR,Y ($0244, Y). If they are equal, branch to RD30 to send EOI . | |
E147 | D9 44 02 | CMP $0244,Y | ||
E14A | F0 01 | BEQ $E14D | ||
E14C | 60 | RTS | Terminate routine with an RTS. | |
RD30 | E14D | A9 81 | LDA #$81 | Load .A with $81 (random access - EOI) and store this as the channel status in CHNRDY,Y ($F2,Y) . |
E14F | 99 F2 00 | STA $00F2,Y | ||
E152 | 60 | RTS | Terminate routine with an RTS. | |
RD40 | E153 | 20 D0 DF | JSR $DFD0 | JSR to NXTREC ($DFD0) to get the next record. |
E156 | 20 2F D1 | JSR $D12F | JSR to GETPRE ($D12F) to set pointers to existing buffer. | |
E159 | A5 85 | LDA $85 | Load .A with the byte from DATA ($85). | |
E15B | 4C 3D E1 | JMP $E13D | JMP to RD25 to carry on. | |
RD05 | E15E | A6 82 | LDX $82 | No record error so load .X with the channel number from LINDX ($82) . |
E160 | A9 0D | LDA #$0D | Store $0D (carriage return) as the data byte in CHNDAT, X ($023E,X). | |
E162 | 9D 3E 02 | STA $023E,X | ||
E165 | A9 81 | LDA #$81 | Load .A with $81 (random access - EOI) and store this as the channel status in CHNRDY,Y ($F2,Y) . | |
E167 | 95 F2 | STA $F2,X | ||
E169 | A9 50 | LDA #$50 | Load .A with $50 (no record error) and abort with a JMP to CMDERR ($C1C8) . | |
E16B | 20 C8 C1 | JSR $C1C8 | ||
SETLST | E16E | A6 82 | LDX $82 | Set pointer to last character in record: Load .X with the channel number from LINDX ($82) |
E170 | B5 C1 | LDA $C1,X | Copy the next record pointer from NR,X ($C1,X) into Rl ($87) . | |
E172 | 85 87 | STA $87 | ||
E174 | C6 87 | DEC $87 | Decrement the pointer in Rl ($87) by 1 and compare the result to $02, the pointer to the first data byte in the sector. If the pointer does not equal $02, branch to SETL01. | |
E176 | C9 02 | CMP #$02 | ||
E178 | D0 04 | BNE $E17E | ||
E17A | A9 FF | LDA #$FF | Store $FF into Rl ($87) so it points to the last byte in a sector. | |
E17C | 85 87 | STA $87 | ||
SETL01 | E17E | B5 C7 | LDA $C7,X | Copy the record size from RS,X ($C7,X) into R2 ($88) . |
E180 | 85 88 | STA $88 | ||
E182 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to get the pointer into the active buffer (returned in .A) Compare this value with the pointer in R1 ($87). If Rl >= .A branch to SETL10. | |
E185 | A6 82 | LDX $82 | ||
E187 | C5 87 | CMP $87 | ||
E189 | 90 19 | BCC $E1A4 | ||
E18B | F0 17 | BEQ $E1A4 | ||
E18D | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. | |
E190 | 20 B2 E1 | JSR $E1B2 | JSR to FNDLST ($E1B2) to find the last character. On return, if carry is clear, branch to SETL05. | |
E193 | 90 08 | BCC $E19D | ||
E195 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E197 | 9D 44 02 | STA $0244,X | Store the character in .A into LSTCHR,X ($0244, X) . | |
E19A | 4C 1E CF | JMP $CF1E | JMP to DBLBUF ($CF1E) to toggle the active and inactive buffers and exit. | |
SETL05 | E19D | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. |
E1A0 | A9 FF | LDA #$FF | Store $FF into Rl ($87) so it points to the last byte in a sector. | |
E1A2 | 85 87 | STA $87 | ||
SETL10 | E1A4 | 20 B2 E1 | JSR $E1B2 | JSR to FNDLST ($E1B2) to find the last non-zero character in the record. On return, if carry set, branch to SETL40. |
E1A7 | B0 03 | BCS $E1AC | ||
E1A9 | 20 E8 D4 | JSR $D4E8 | JSR to GETPNT ($D4E8) to get the pointer into the active buffer (returned in .A) | |
SETL40 | E1AC | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
E1AE | 9D 44 02 | STA $0244,X | Store the character in .A into LSTCHR,X ($0244, X) . | |
E1B1 | 60 | RTS | Terminate routine with an RTS. | |
Find last non-zero character in record |
||||
FNDLST | E1B2 | 20 2B DE | JSR $DE2B | JSR to SET00 ($DE2B) to set up pointer to start of buffer. |
E1B5 | A4 87 | LDY $87 | Load .Y with the offset to start at from Rl ($87) . | |
FNDL10 | E1B7 | B1 94 | LDA ($94),Y | Load .A with the data byte from the buffer at (DIRBUF) ,Y; ($94), Y. If the data byte is not $00, branch to FNDL20. |
E1B9 | D0 0D | BNE $E1C8 | ||
E1BB | 88 | DEY | Decrement the pointer in .Y. If the resulting pointer is less than or equal to $02, branch to FNDL30 since the start of the record is not in here. | |
E1BC | C0 02 | CPY #$02 | ||
E1BE | 90 04 | BCC $E1C4 | ||
E1C0 | C6 88 | DEC $88 | Decrement the record size in R2 ($88) . If R2 has not counted down to $00 yet, branch FNDL10. | |
E1C2 | D0 F3 | BNE $E1B7 | ||
FNDL30 | E1C4 | C6 88 | DEC $88 | Decrement the record size in R2 ($88) . Clear the carry flag to indicate that the record was not found here and exit from the routine with an RTS. |
E1C6 | 18 | CLC | ||
E1C7 | 60 | RTS | ||
FNDL20 | E1C8 | 98 | TYA | Found the last non-zero character so transfer the pointer from .Y to .A. |
E1C9 | 38 | SEC | Set the carry flag to indicate it was found here and terminate with an RTS. | |
E1CA | 60 | RTS | ||
E1CB | 20 D2 DE | JSR $DED2 | ||
SSEND | E1CE | 85 D5 | STA $D5 | Set SS & BUFTAB to end of last record: JSR to SSSET ($DED2) to set the SS pointer to $00. Store the side sector number returned in .A into SSNUM ($D5) . |
E1D0 | A9 04 | LDA #$04 | Set the lo byte of the pointer in DIRBUF ($94) to $04. | |
E1D2 | 85 94 | STA $94 | ||
E1D4 | A0 0A | LDY #$0A | Load .Y with $A0 (the side sector offset, less 6) and branch to SE20 (always) . | |
E1D6 | D0 04 | BNE $E1DC | ||
SE10 | E1D8 | 88 | DEY | Decrement pointer in. Y by 2. If the result is less than $00, branch to BREAK |
E1D9 | 88 | DEY | ||
E1DA | 30 26 | BMI $E202 | ||
SE20 | E1DC | B1 94 | LDA ($94),Y | Look for the last SS number by loading .A from (DIRBUF) ,Y; ($94) ,Y. If the byte is $00, we have not found it yet so branch back to SE10. |
E1DE | F0 F8 | BEQ $E1D8 | ||
E1E0 | 98 | TYA | Transfer the pointer in .Y into .A. | |
E1E1 | 4A | LSR | Multiply the pointer in .A by 2 (ASL) and compare the result to the side sector number in SSNUM ($D5). If they are equal, this is the last SS number so branch to SE30. | |
E1E2 | C5 D5 | CMP $D5 | ||
E1E4 | F0 09 | BEQ $E1EF | ||
E1E6 | 85 D5 | STA $D5 | Store the SS number in .A into SSNUM ($D5) . | |
E1E8 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E1EA | B5 CD | LDA $CD,X | Load .A with the side sector from SS,X ($CD,X) and JSR to IBRD ($DF1B) to do an indirect block read of the last side sector. | |
E1EC | 20 1B DF | JSR $DF1B | ||
SE30 | E1EF | A0 00 | LDY #$00 | Zero .Y and set the lo byte of the pointer in DIRBUF ($94) to $00. |
E1F1 | 84 94 | STY $94 | ||
E1F3 | B1 94 | LDA ($94),Y | Load .A with track link from (DIRBUF) ,Y ($94), Y. If the link is not $00, branch to BREAK. | |
E1F5 | D0 0B | BNE $E202 | ||
E1F7 | C8 | INY | Increment .Y | |
E1F8 | B1 94 | LDA ($94),Y | Load .A with sector link from (DIRBUF) ,Y ($94) ,Y. This points to the last good byte in the buffer. Transfer the pointer to .Y, decrement it by 1, store it in SSIND ($D6). and transfer it back to .A. | |
E1FA | A8 | TAY | ||
E1FB | 88 | DEY | ||
E1FC | 84 D6 | STY $D6 | ||
E1FE | 98 | TYA | ||
E1FF | 4C E9 DE | JMP $DEE9 | JMP to SETSSP ($DEE9) to set DIRBUF and BUFTAB with current SS pointer. | |
BREAK | E202 | A9 67 | LDA #$67 | Load .A with $67 to indicate a SYSTEM TRACK OR SECTOR error and JSR to CMDERR2 ($E645) . |
E204 | 20 45 E6 | JSR $E645 | ||
Record command |
||||
Position pointer to given recordNote: set to last record if out of range |
||||
RECORD | E207 | 20 B3 C2 | JSR $C2B3 | JSR to CMDSET($C2B3) to initialize the pointers and tables . |
E20A | AD 01 02 | LDA $0201 | Load .A with the second character in the command from CMDBUF+1 ($0201) and use it to set the secondary address in SA ($83) | |
E20D | 85 83 | STA $83 | ||
E20F | 20 EB D0 | JSR $D0EB | JSR to FNDRCH($D0EB) to find an unused read channel. | |
E212 | 90 05 | BCC $E219 | If carry flag clear, channel found so branch to R20 | |
E214 | A9 70 | LDA #$70 | Load .A with $70 to indicate a NO CHANNEL error and JSR to CMDERR ($C1C8). | |
E216 | 20 C8 C1 | JSR $C1C8 | ||
R20 | E219 | A9 A0 | LDA #$A0 | Load .A with $A0 (last record flag plus overflow flag) and JSR to CLRFLG ($DD9D) to clear these flags. |
E21B | 20 9D DD | JSR $DD9D | ||
E21E | 20 25 D1 | JSR $D125 | JSR to TYPFIL ($D125) to determine the file type. If the Z flag is set, it is a relative file so branch to R30. | |
E221 | F0 05 | BEQ $E228 | ||
E223 | A9 64 | LDA #$64 | Load .A with $64 to indicate a FILE TYPE MISMATCH error and JSR to CMDERR ($C1C8) | |
E225 | 20 C8 C1 | JSR $C1C8 | ||
R30 | E228 | B5 EC | LDA $EC,X | Load .A with the file type from FILTYP,X ($EC,X), AND the type with $01 to mask off the non-drive bits, and store the result as the drive # in DRVNUM ($7F) . |
E22A | 29 01 | AND #$01 | ||
E22C | 85 7F | STA $7F | ||
E22E | AD 02 02 | LDA $0202 | Load .A with the third character in the command from CMDBUF+2 ($0202) and use it to set the lo byte of the record number in RECL,X ($B5,X) . | |
E231 | 95 B5 | STA $B5,X | ||
E233 | AD 03 02 | LDA $0203 | Load .A with the fourth character in the command from CMDBUF+3 ($0203) and use it to set the hi byte of the record number in RECH,X ($BB,X) . | |
E236 | 95 BB | STA $BB,X | ||
E238 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E23A | A9 89 | LDA #$89 | Store $89 (random access - ready) as the channel status in CHNRDY,X ($F2,X). | |
E23C | 95 F2 | STA $F2,X | ||
E23E | AD 04 02 | LDA $0204 | Load .A with the fifth character in the command from CMDBUF+4 ($0204). This is the byte pointer into the record. If the byte pointer is $00, branch to R40. | |
E241 | F0 10 | BEQ $E253 | ||
E243 | 38 | SEC | Set the carry flag and subtract $01 from the byte pointer. If the result is $00, branch to R40. | |
E244 | E9 01 | SBC #$01 | ||
E246 | F0 0B | BEQ $E253 | ||
E248 | D5 C7 | CMP $C7,X | Compare the adjusted byte pointer to the record size in RS,X ($C7,X). If the byte pointer is within the record, branch to R40. | |
E24A | 90 07 | BCC $E253 | ||
E24C | A9 51 | LDA #$51 | Load .A with $51 (record overflow) and store it in ERWORD ($026C). Zero .A. | |
E24E | 8D 6C 02 | STA $026C | ||
E251 | A9 00 | LDA #$00 | ||
R40 | E253 | 85 D4 | STA $D4 | Store the byte pointer (in .A) into RECPTR ($D4) . |
E255 | 20 0E CE | JSR $CE0E | JSR to FNDREL ($CE0E) to calculate the side sector pointers. | |
E258 | 20 F8 DE | JSR $DEF8 | JSR to SSPOS ($DEF8) to set the side sector pointers. If V flag is clear, we have not attempted to go beyond the last record so branch to R50. | |
E25B | 50 08 | BVC $E265 | ||
E25D | A9 80 | LDA #$80 | Load .A with $80 (last record flag) and JSR to SETFLG ($DD97) to set the flag. | |
E25F | 20 97 DD | JSR $DD97 | ||
E262 | 4C 5E E1 | JMP $E15E | JMP to RD05 ($E15E) to set pointers to the last record. | |
R50 | E265 | 20 75 E2 | JSR $E275 | JSR to POSITN ($E275) to position to the desired record. |
E268 | A9 80 | LDA #$80 | Load .A with $80 (last record flag) and JSR to TSTFLG ($DDA6) to test if this flag has been set. If not, branch to R60 to exit. | |
E26A | 20 A6 DD | JSR $DDA6 | ||
E26D | F0 03 | BEQ $E272 | ||
E26F | 4C 5E E1 | JMP $E15E | JMP to RD05 ($E15E) to set pointers to the last record. | |
R60 | E272 | 4C 94 C1 | JMP $C194 | JMP to ENDCMD ($C194) to terminate. |
Position to recordMoves relative record into active buffer and the next block into inactive buffer, |
||||
POSITN | E275 | 20 9C E2 | JSR $E29C | JSR to POSBUF ($E29C) to position data blocks into buffers. |
E278 | A5 D7 | LDA $D7 | Load .A with the pointer from RELPNT ($D7) and JSR to SETPNT ($D4C8) to set up the buffer pointers. | |
E27A | 20 C8 D4 | JSR $D4C8 | ||
E27D | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E27F | B5 C7 | LDA $C7,X | Load .A with the record size from RS,X (C7,X) and set the carry flag. | |
E281 | 38 | SEC | ||
E282 | E5 D4 | SBC $D4 | Subtract the pointer in RECPNT ($D4) from the record size in .A to find the offset. If offset > $00,branch to P2. | |
E284 | B0 03 | BCS $E289 | ||
E286 | 4C 02 E2 | JMP $E202 | Trouble! JMP to BREAK ($E202) . | |
P2 | E289 | 18 | CLC | Clear the carry flag and add the pointer in RELPNT ($D7). If there is no carry, branch to P30. |
E28A | 65 D7 | ADC $D7 | ||
E28C | 90 03 | BCC $E291 | ||
E28E | 69 01 | ADC #$01 | Add another $01 and set the carry flag. | |
E290 | 38 | SEC | ||
P30 | E291 | 20 09 E0 | JSR $E009 | JSR to NXOUT ($E009) to set up the next record. |
E294 | 4C 38 E1 | JMP $E138 | JMP to RD15 ($E138) to complete set up. | |
Unused code |
||||
E297 | A9 51 | LDA #$51 | Load .A with $51 (record overflow) and JSR to CMDERR ($C1C8). | |
E299 | 20 C8 C1 | JSR $C1C8 | ||
Position proper data blocks into buffers |
||||
POSBUF | E29C | A5 94 | LDA $94 | Save the lo byte of the DIRBUF ($94/5) pointer into R3 ($89). |
E29E | 85 89 | STA $89 | ||
E2A0 | A5 95 | LDA $95 | Save the hi byte of the DIRBUF ($94/5) pointer into R4 ($8A) . | |
E2A2 | 85 8A | STA $8A | ||
E2A4 | 20 D0 E2 | JSR $E2D0 | JSR to BHERE ($E2D0) to check if desired block is in the buffer. If not, branch to P10 to read it in. | |
E2A7 | D0 01 | BNE $E2AA | ||
E2A9 | 60 | RTS | Terminate routine with an RTS. | |
P10 | E2AA | 20 F1 DD | JSR $DDF1 | JSR to SCRUB ($DDF1) to clean the buffer |
E2AD | 20 0C DE | JSR $DE0C | JSR to GETLNK ($DE0C) to set TRACK and SECTOR from the link. | |
E2B0 | A5 80 | LDA $80 | If TRACK ($80) is $00, there is no next track so branch to P80. | |
E2B2 | F0 0E | BEQ $E2C2 | ||
E2B4 | 20 D3 E2 | JSR $E2D3 | JSR to BHERE ($E2D0) to check if desired block is in the buffer. If not, branch to P75 to read it in. | |
E2B7 | D0 06 | BNE $E2BF | ||
E2B9 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle the active and inactive buffers. | |
E2BC | 4C DA D2 | JMP $D2DA | JMP to FREIAC ($D2DA) to free the inactive buffer. | |
P75 | E2BF | 20 DA D2 | JSR $D2DA | JSR to FREIAC ($D2DA) to free the inactive buffer. |
P80 | E2C2 | A0 00 | LDY #$00 | Load .Y with $00. |
E2C4 | B1 89 | LDA ($89),Y | Move the desired track from (R3),Y ($89), Y into TRACK ($80). Increment .Y | |
E2C6 | 85 80 | STA $80 | ||
E2C8 | C8 | INY | ||
E2C9 | B1 89 | LDA ($89),Y | Move the desired sector from (R3),Y ($89), Y into SECTOR ($81). | |
E2CB | 85 81 | STA $81 | ||
E2CD | 4C AF D0 | JMP $D0AF | JMP to STRDBL ($D0AF) to read in the desired block and the next one too. | |
BHERE | E2D0 | 20 3E DE | JSR $DE3E | Check if desired block is in buffer: JSR to GETHDR ($DE3E) to set TRACK and SECTOR from the header. |
BHERE2 | E2D3 | A0 00 | LDY #$00 | Load .Y with $00 |
E2D5 | B1 89 | LDA ($89),Y | Compare the desired track from (R3) ,Y ($89), Y with the value in TRACK ($80). If they are equal, branch to BH10 to compare the sectors. | |
E2D7 | C5 80 | CMP $80 | ||
E2D9 | F0 01 | BEQ $E2DC | No match (Z=0) so exit with an RTS | |
E2DB | 60 | RTS | ||
BH10 | E2DC | C8 | INY | Increment .Y. |
E2DD | B1 89 | LDA ($89),Y | Compare the desired sector from (R3),Y ($89) ,Y with the value in SECTOR ($81) . This sets Z=l if they are equal. | |
E2DF | C5 81 | CMP $81 | ||
E2E1 | 60 | RTS | Terminate routine with an RTS. | |
Set null records in active buffer |
||||
NULBUF | E2E2 | 20 2B DE | JSR $DE2B | JSR to SETOO ($DE2B) to set pointers to start of data buffer. |
E2E5 | A0 02 | LDY #$02 | Loop to fill data buffer with $00' s from $xx02 to $xxFF. | |
E2E7 | A9 00 | LDA #$00 | ||
E2E9 | 91 94 | STA ($94),Y | ||
E2EB | C8 | INY | ||
E2EC | D0 FB | BNE $E2E9 | ||
E2EE | 20 04 E3 | JSR $E304 | JSR to ADDNR ($E304) to calculate the position of the next record (in .A) . | |
NB20 | E2F1 | 95 C1 | STA $C1,X | Store the new pointer value in NR,X ($C1,X) . |
E2F3 | A8 | TAY | Transfer the next record pointer to .Y. | |
E2F4 | A9 FF | LDA #$FF | Store $FF as the first character in the next record at (DIRBUF) ,Y; ($94), Y. | |
E2F6 | 91 94 | STA ($94),Y | ||
E2F8 | 20 04 E3 | JSR $E304 | JSR to ADDNR ($E304) to calculate the position of the next record (in .A) . | |
E2FB | 90 F4 | BCC $E2F1 | If carry flag is clear, we haven't done all the records in this block yet so branch to NB20. | |
E2FD | D0 04 | BNE $E303 | If the Z flag is not set, branch to NB30 | |
E2FF | A9 00 | LDA #$00 | Store $00 into NR,X ($C1,X) to flag the last record. | |
E301 | 95 C1 | STA $C1,X | ||
NB30 | E303 | 60 | RTS | Terminate routine with an RTS. |
Add record size & next record pointerOn exit: C=1 if crossed buffer boundary |
||||
ADDNR | E304 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
E306 | B5 C1 | LDA $C1,X | Load .A with the next record pointer from NR,X ($C1,X) and set the carry flag | |
E308 | 38 | SEC | ||
E309 | F0 0D | BEQ $E318 | If NR pointer is $00 branch to AN05. | |
E30B | 18 | CLC | Clear the carry flag and add the record size from RS,X ($C7,X) . | |
E30C | 75 C7 | ADC $C7,X | ||
E30E | 90 0B | BCC $E31B | If carry clear, branch to AN10. | |
E310 | D0 06 | BNE $E318 | If result is not $00, branch to AN05. | |
E312 | A9 02 | LDA #$02 | Load .A with $02(bypass link) | |
E314 | 2C CC FE | BIT $FECC | BIT with ER00 ($FECC) to set flags, | |
E317 | 60 | RTS | Terminate routine with an RTS | |
AN05 | E318 | 69 01 | ADC #$01 | Add $01 to the contents of .A to adjust for the link and set the carry flag. |
E31A | 38 | SEC | ||
AN10 | E31B | 60 | RTS | Terminate routine with an RTS |
Add blocks to a relative file |
||||
ADDREL | E31C | 20 D3 D1 | JSR $D1D3 | JSR to SETDRN ($D1D3) to set drive #. |
E31F | 20 CB E1 | JSR $E1CB | JSR to SSEND ($E1CB) to set up end of file. | |
E322 | 20 9C E2 | JSR $E29C | JSR to POSBUF ($E29C) to position the proper data blocks into the buffers. | |
E325 | 20 7B CF | JSR $CF7B | JSR to DBSET ($CF7C) to set up double buffering. | |
E328 | A5 D6 | LDA $D6 | Copy side sector index from SSIND ($D6) into R1 ($87) . | |
E32A | 85 87 | STA $87 | ||
E32C | A5 D5 | LDA $D5 | Copy side sector number from SSNUM ($D5) into R0 ($86) . | |
E32E | 85 86 | STA $86 | ||
E330 | A9 00 | LDA #$00 | Set R2 ($88) to $00 to clear the flag fcr one block. | |
E332 | 85 88 | STA $88 | ||
E334 | A9 00 | LDA #$00 | Set RECPTR ($D4) to $00 to clear this for calculations. | |
E336 | 85 D4 | STA $D4 | ||
E338 | 20 0E CE | JSR $CE0E | JSR to FNDREL ($CE0E) to calculate the side sector pointers. | |
ADDR1 | E33B | 20 4D EF | JSR $EF4D | JSR to NUMFRE ($EF4D) to calculate the number of blocks free. |
E33E | A4 82 | LDY $82 | Load .Y with the channel number from LINDX ($82) . | |
E340 | B6 C7 | LDX $C7,Y | Load .X with the record size from RS,Y ($C7,Y), decrement the size by 1, and transfer the result into .A. | |
E342 | CA | DEX | ||
E343 | 8A | TXA | ||
E344 | 18 | CLC | Clear the carry flag and add the record pointer, RELPTR ($D7) to the record size in .A. | |
E345 | 65 D7 | ADC $D7 | ||
E347 | 90 0C | BCC $E355 | If no carry results, there is no span to the next block so branch to AR10. | |
E349 | E6 D6 | INC $D6 | Increment the SS pointer, SSIND ($D6) twice. If the result is not zero, branch to AR10. | |
E34B | E6 D6 | INC $D6 | ||
E34D | D0 06 | BNE $E355 | ||
E34F | E6 D5 | INC $D5 | Increment the side sector number, SSNUM (D5) by 1 and store $10 (the side sector offset) into SSIND ($D6) since we are starting a new block. | |
E351 | A9 10 | LDA #$10 | ||
E353 | 85 D6 | STA $D6 | ||
AR10 | E355 | A5 87 | LDA $87 | Load .A with the SS index from Rl. clear the carry flag, add $02, and JSR to SETSSP ($DEE9) to set DIRBUF & BUFTAB. |
E357 | 18 | CLC | ||
E358 | 69 02 | ADC #$02 | ||
E35A | 20 E9 DE | JSR $DEE9 | ||
E35D | A5 D5 | LDA $D5 | Load the side sector number from SSNUM ($D5) and compare it with $06, the number of side sector links. If SSNUM is less than or equal to $06, the range is valid so branch to AR25. | |
E35F | C9 06 | CMP #$06 | ||
E361 | 90 05 | BCC $E368 | ||
AR20 | E363 | A9 52 | LDA #$52 | Load .A with $52 to indicate a TOO BIG RELATIVE FILE error and JSR to CMDERR ($C1C8) . |
E365 | 20 C8 C1 | JSR $C1C8 | ||
AR25 | E368 | A5 D6 | LDA $D6 | Load .A with the side sector index from SSIND ($D6) and set the carry flag. |
E36A | 38 | SEC | ||
E36B | E5 87 | SBC $87 | Subtract the SS index from Rl ($87). If the result is positive, branch to AR30. | |
E36D | B0 03 | BCS $E372 | ||
E36F | E9 0F | SBC #$0F | Subtract $0F (the side sector index offset less 1) and clear the carry flag. | |
E371 | 18 | CLC | ||
AR30 | E372 | 85 72 | STA $72 | Store the number of side sector indicies (in .A) into T3 ($72) . |
E374 | A5 D5 | LDA $D5 | Load .A with the SS number from SSNUM ($D5). Subtract the SS number from R0 ($86) to find the number of side sectors needed. Store the number needed into T4 ($73) . | |
E376 | E5 86 | SBC $86 | ||
E378 | 85 73 | STA $73 | ||
E37A | A2 00 | LDX #$00 | Zero Tl ($70) and T2 ($71) to serve as a results accumulator. | |
E37C | 86 70 | STX $70 | ||
E37E | 86 71 | STX $71 | ||
E380 | AA | TAX | Transfer the number of side sectors needed from .A to .X and JSR to SSCALC ($DF51) to calculate the number of blocks needed. | |
E381 | 20 51 DF | JSR $DF51 | ||
E384 | A5 71 | LDA $71 | Load .A with the hi byte of the number needed from T2 ($71). If the hi byte is not $00, branch to AR35. | |
E386 | D0 07 | BNE $E38F | ||
E388 | A6 70 | LDX $70 | Load .X with the lo byte of the number needed from Tl ($70). Decrement .X by 1. If the result is not $00, branch to AR35 | |
E38A | CA | DEX | ||
E38B | D0 02 | BNE $E38F | ||
E38D | E6 88 | INC $88 | Increment R2 ($88) by 1. | |
Check if there are enough blocks left |
||||
AR35 | E38F | CD 73 02 | CMP $0273 | Compare the hi byte of the number of blocks needed (in .A) with the hi byte of the number of blocks free in NBTEMP+1 ($0273). If there are more than enough, branch to AR40. If there are NOT enough, branch to AR20. If we have just enough, we had better check the lo byte. |
E392 | 90 09 | BCC $E39D | ||
E394 | D0 CD | BNE $E363 | ||
E396 | AD 72 02 | LDA $0272 | Load .A with the lo byte of the number free from NBTEMP ($0272) and compare it with the lo byte of the number needed in T1 ($70). If there are not enough, branch to AR20 to abort. | |
E399 | C5 70 | CMP $70 | ||
E39B | 90 C6 | BCC $E363 | ||
AR40 | E39D | A9 01 | LDA #$01 | Load .A with $01 and JSR to DRDBYT ($D4F6) to read the sector link. |
E39F | 20 F6 D4 | JSR $D4F6 | ||
E3A2 | 18 | CLC | Clear the carry flag and add $01 to .A to give the NR. | |
E3A3 | 69 01 | ADC #$01 | ||
E3A5 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E3A7 | 95 C1 | STA $C1,X | Store the NR value (in .A) into NR,X ($C1,X) . | |
E3A9 | 20 1E F1 | JSR $F11E | JSR to NXTTS ($F11E) to get the next available track and sector. | |
E3AC | 20 FD DD | JSR $DDFD | JSR to SETLNK ($DDFD) to set the track and sector link in the current block. | |
E3AF | A5 88 | LDA $88 | Load .A with the add-1-block flag from R2 ($88). If the flag is set, branch to AR50. | |
E3B1 | D0 15 | BNE $E3C8 | ||
E3B3 | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write the current block to disk. | |
AR45 | E3B6 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E)to switch buffers, |
E3B9 | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0)to set header from TRACK and SECTOR. | |
E3BC | 20 1E F1 | JSR $F11E | JSR to NXTTS ($F11E) to get. the next, available track and sector. | |
E3BF | 20 FD DD | JSR $DDFD | JSR to SETLNK ($DDFD) to set the track and sector link in the current block. | |
E3C2 | 20 E2 E2 | JSR $E2E2 | JSR to NULBUF ($E2E2) to clean out the buffer | |
E3C5 | 4C D4 E3 | JMP $E3D4 | JMP to AR55 ($E3D4) . | |
AR50 | E3C8 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to switch buffers. |
E3CB | 20 D0 D6 | JSR $D6D0 | JSR to SETHDR ($D6D0) to set header from TRACK and SECTOR. | |
E3CE | 20 E2 E2 | JSR $E2E2 | JSR to NULBUF ($E2E2) to clean out the buffer | |
E3D1 | 20 19 DE | JSR $DE19 | JSR to NULLNK ($DE19) to set link for the last block. | |
AR55 | E3D4 | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write the current block to disk. |
E3D7 | 20 0C DE | JSR $DE0C | JSR to GETLNK ($DE0C) to set TRACK and SECTOR from the track & sector link. | |
E3DA | A5 80 | LDA $80 | Save the value of TRACK ($80) and SECTOR ($81) onto the stack. | |
E3DC | 48 | PHA | ||
E3DD | A5 81 | LDA $81 | ||
E3DF | 48 | PHA | ||
E3E0 | 20 3E DE | JSR $DE3E | JSR to GETHDR ($DE3E) to set TRACK and SECTOR from the last sector read. | |
E3E3 | A5 81 | LDA $81 | Save the value of TRACK ($80) and SECTOR ($81) onto the stack. | |
E3E5 | 48 | PHA | ||
E3E6 | A5 80 | LDA $80 | ||
E3E8 | 48 | PHA | ||
E3E9 | 20 45 DF | JSR $DF45 | JSR to GSSPNT ($DF45) to calculate the side sector pointer (returned in .A) | |
E3EC | AA | TAX | Transfer the pointer in .A to .X. If the pointer value is not $00, we don't need another side sector so branch to AR60. | |
E3ED | D0 0A | BNE $E3F9 | ||
E3EF | 20 4E E4 | JSR $E44E | JSR to NEWSS ($E44E) to get another side sector. | |
E3F2 | A9 10 | LDA #$10 | Load .A with $10, side sector offset, and JSR to SETSSP ($DEE9) to set the side sector pointer. | |
E3F4 | 20 E9 DE | JSR $DEE9 | ||
E3F7 | E6 86 | INC $86 | Increment the side sector count in R0 ($86) by 1. | |
AR60 | E3F9 | 68 | PLA | Pull this sector's track off the stack and JSR to PUTSS ($DD8D) to write it into the side sector buffer. |
E3FA | 20 8D DD | JSR $DD8D | ||
E3FD | 68 | PLA | Pull this sector's sector off the stack and JSR to PUTSS ($DD8D) to write it into the side sector buffer. | |
E3FE | 20 8D DD | JSR $DD8D | ||
E401 | 68 | PLA | Pull this sector's sector link off the stack and store it in SECTOR ($81) . | |
E402 | 85 81 | STA $81 | ||
E404 | 68 | PLA | Pull this sector's track link off the stack and store it in TRACK ($80) . | |
E405 | 85 80 | STA $80 | ||
E407 | F0 0F | BEQ $E418 | If track link is $00, there are no more blocks in this file so branch to AR65 | |
E409 | A5 86 | LDA $86 | Compare the side sector counter in R0 ($86) with the end count in SSNUM ($D5) . If they are not equal, we haven't done enough new blocks yet so branch to AR45. | |
E40B | C5 D5 | CMP $D5 | ||
E40D | D0 A7 | BNE $E3B6 | ||
E40F | 20 45 DF | JSR $DF45 | Almost done so JSR to GSSPNT ($DF45) to get the side sector pointer. | |
E412 | C5 D6 | CMP $D6 | Compare the pointer in .A with the end pointer in SSIND($D6). If SSIND>.A, we are almost done so branch to AR45. If SSIND=.A there is one more block left so branch to AR50. | |
E414 | 90 A0 | BCC $E3B6 | ||
E416 | F0 B0 | BEQ $E3C8 | ||
AR65 | E418 | 20 45 DF | JSR $DF45 | All done. JSR to GSSPNT ($DF45) to get the side sector pointer. Save it onto the stack. |
E41B | 48 | PHA | ||
E41C | A9 00 | LDA #$00 | Load .A with a $00 and JSR to SSDIR ($DEDC) to set DIRBUF with the current SS pointer. | |
E41E | 20 DC DE | JSR $DEDC | ||
E421 | A9 00 | LDA #$00 | Zero .A and .Y. Zero the track link of the side-sector sector in (DIRBUF) ,Y ($94) ,Y. Increment .Y. | |
E423 | A8 | TAY | ||
E424 | 91 94 | STA ($94),Y | ||
E426 | C8 | INY | ||
E427 | 68 | PLA | Pull the pointer into this sector off the stack, subtract $01, and store the result as the sector link of the side- sector sector in (DIRBUF) ,Y; ($94) ,Y. | |
E428 | 38 | SEC | ||
E429 | E9 01 | SBC #$01 | ||
E42B | 91 94 | STA ($94),Y | ||
E42D | 20 6C DE | JSR $DE6C | JSR to WRTSS ($DE6C) to write out the current block of side sectors to disk. | |
E430 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the write job to be completed. | |
E433 | 20 F4 EE | JSR $EEF4 | JSR to MAPOUT ($EEF4) to write the BAM. | |
E436 | 20 0E CE | JSR $CE0E | JSR to FNDREL ($CE0E) to find the relative file and calculate SSNUM and SSIND for the desired record. | |
E439 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to get back to the leading buffer. | |
E43C | 20 F8 DE | JSR $DEF8 | JSR to SSPOS ($DEF8) to position SS and BUFTAB to SSNUM and SSIND. | |
E43F | 70 03 | BVS $E444 | On return, if V flag is set, the record is still beyond the end of the relative file so branch to AR70. | |
E441 | 4C 75 E2 | JMP $E275 | All OK so exit from routine with a JMP to POSITN ($E275) to position to the record. | |
AR70 | E444 | A9 80 | LDA #$80 | Still beyond end of file so: load .A with $80 (the last record flag). JSR to SETFLG ($DD97) to set the flag, load .A with $50 (no record error) and exit with a JSR to CMDERR ($C1C8). |
E446 | 20 97 DD | JSR $DD97 | ||
E449 | A9 50 | LDA #$50 | ||
E44B | 20 C8 C1 | JSR $C1C8 | ||
Create a new side sector and change the old side sectors to reflect, it. |
||||
NEWSS | E44E | 20 1E F1 | JSR $F11E | JSR to NXTTS ($F11E) to find the next- available track and sector. |
E451 | 20 1E CF | JSR $CF1E | JSR to DBLBUF ($CF1E) to toggle to the inactive buffer. | |
E454 | 20 F1 DD | JSR $DDF1 | JSR to SCRUB ($DDF1) to write out the buffer if it is dirty (doesn't match copy on disk) . | |
E457 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to determine the active buffer number (returned in .A) . Save the buffer number onto the stack. | |
E45A | 48 | PHA | ||
E45B | 20 C1 DE | JSR $DEC1 | JSR to CLRBUF ($DEC1) to zero the buffer | |
E45E | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E460 | B5 CD | LDA $CD,X | Load .A with the number of the buffer containing the side sectors from SS,X ($CD,X) and transfer this value into .Y. | |
E462 | A8 | TAY | ||
E463 | 68 | PLA | Pull the active buffer number off the stack and transfer it into .X. | |
E464 | AA | TAX | ||
E465 | A9 10 | LDA #$10 | Load .A with $10, the side sector offset | |
E467 | 20 A5 DE | JSR $DEA5 | JSR to B0TOB0 ($DEA5) to move $10 (.A) bytes from buffer #(.X) to buffer #(.Y). | |
E46A | A9 00 | LDA #$00 | Load .A with $00 and JSR to SSDIR($DEDC) to set the pointer at DIRBUF ($94) to point to the start of the old SS buffer. | |
E46C | 20 DC DE | JSR $DEDC | ||
E46F | A0 02 | LDY #$02 | Load .Y with $02. and load .A with the side sector number from (DIRBUF) ,Y and save it onto the stack. | |
E471 | B1 94 | LDA ($94),Y | ||
E473 | 48 | PHA | ||
E474 | A9 00 | LDA #$00 | Zero .A and JSR to SETPNT ($D4C8) to set the pointer at DIRBUF ($94) to point to the start of the new SS buffer. | |
E476 | 20 C8 D4 | JSR $D4C8 | ||
E479 | 68 | PLA | Pull the SS number off the stack, add 1, and store the result in the new side sector table at (DIRBUF) ,Y. | |
E47A | 18 | CLC | ||
E47B | 69 01 | ADC #$01 | ||
E47D | 91 94 | STA ($94),Y | ||
E47F | 0A | ASL | Multiply the SS number in .A by 2 (ASL) , add 4, store the result (points to the new SS value in the buffer) in R3 ($89) , and transfer this value into .Y. | |
E480 | 69 04 | ADC #$04 | ||
E482 | 85 89 | STA $89 | ||
E484 | A8 | TAY | ||
E485 | 38 | SEC | Subtract $02 from the result and store this pointer in R2 ($88) . | |
E486 | E9 02 | SBC #$02 | ||
E488 | 85 8A | STA $8A | ||
E48A | A5 80 | LDA $80 | Copy the current value of TRACK ($80) into Rl ($87) for use in SS update and into the new SS buffer at (DIRBUF) ,Y | |
E48C | 85 87 | STA $87 | ||
E48E | 91 94 | STA ($94),Y | ||
E490 | C8 | INY | Increment .Y | |
E491 | A5 81 | LDA $81 | Copy the current value of SECTOR ($81) into R2 ($88) for use in SS update and into the new SS buffer at (DIRBUF) ,Y | |
E493 | 85 88 | STA $88 | ||
E495 | 91 94 | STA ($94),Y | ||
E497 | A0 00 | LDY #$00 | Set the track link at the start of the new SS block to $00. | |
E499 | 98 | TYA | ||
E49A | 91 94 | STA ($94),Y | ||
E49C | C8 | INY | Set the sector link at the start of the new SS block to $11 to indicate that the last, non-zero character in the buffer is the one following the SS offset. | |
E49D | A9 11 | LDA #$11 | ||
E49F | 91 94 | STA ($94),Y | ||
E4A1 | A9 10 | LDA #$10 | Load .A with $10 (the SS offset) and JSR to SETPNT ($D4C8) to set the pointer to the new SS block. | |
E4A3 | 20 C8 D4 | JSR $D4C8 | ||
E4A6 | 20 50 DE | JSR $DE50 | JSR to WRTAB ($DE50) to write out the new side sector block to disk. | |
E4A9 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the write job to be completed. | |
|
||||
NS20 | E4AC | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . |
E4AE | B5 CD | LDA $CD,X | Load .A with the side sector buffer number from SS,X ($CD,X) and save this number onto the stack. | |
E4B0 | 48 | PHA | ||
E4B1 | 20 9E DF | JSR $DF9E | JSR to GAFLGS ($DF9E) to get active buffer number and set flags. | |
E4B4 | A6 82 | LDX $82 | Load .X with the new channel number from LINDX ($82) . | |
E4B6 | 95 CD | STA $CD,X | Store the side sector buffer number from .A into SS,X ($CD,X). Note: this swaps the active buffer and the SS buffer. | |
E4B8 | 68 | PLA | Pull the old side sector buffer number off the stack, load .X with the last buffer used from LBUSED ($0257). and store the old SS buffer # (in .A) into BUF0,X ($A7,X) . | |
E4B9 | AE 57 02 | LDX $0257 | ||
E4BC | 95 A7 | STA $A7,X | ||
E4BE | A9 00 | LDA #$00 | Zero .A and JSR to SETPNT ($D4C8) to set the buffer pointer to the start of the buffer. | |
E4C0 | 20 C8 D4 | JSR $D4C8 | ||
E4C3 | A0 00 | LDY #$00 | Zero .Y and set the track link to point- to the new SS block using the value from TRACK ($80). Increment .Y. | |
E4C5 | A5 80 | LDA $80 | ||
E4C7 | 91 94 | STA ($94),Y | ||
E4C9 | C8 | INY | ||
E4CA | A5 81 | LDA $81 | Set the sector link to point to the new SS block using the value from SECTOR ($81) . | |
E4CC | 91 94 | STA ($94),Y | ||
E4CE | 4C DE E4 | JMP $E4DE | JMP to NS50 ($E4DE) . | |
NS40 | E4D1 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . |
E4D4 | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
E4D6 | 20 1B DF | JSR $DF1B | JSR to IBRD ($DF1B) to read the next SS. buffer number (returned in .A) . | |
E4D9 | A9 00 | LDA #$00 | ||
E4DB | 20 C8 D4 | JSR $D4C8 | Zero .A and JSR to SETPNT ($D4C8) to set the buffer pointer to the start of the buffer. | |
NS50 | E4DE | C6 8A | DEC $8A | Decrement the pointer in R4 ($8A) twice. |
E4E0 | C6 8A | DEC $8A | ||
E4E2 | A4 89 | LDY $89 | Load .Y with the pointer into the buffer from R3 ($89) . | |
E4E4 | A5 87 | LDA $87 | Load .A with the new SS track pointer from Rl ($87) and store this value into the data buffer at (DIRBUF) ,Y. | |
E4E6 | 91 94 | STA ($94),Y | ||
E4E8 | C8 | INY | Increment .Y. | |
E4E9 | A5 88 | LDA $88 | Load .A with the new SS sector pointer from R2 ($88) and store this value into the data buffer at (DIRBUF) ,Y . | |
E4EB | 91 94 | STA ($94),Y | ||
E4ED | 20 5E DE | JSR $DE5E | JSR to WRTOUT ($DE5E) to write out the revised side sector block. | |
E4F0 | 20 99 D5 | JSR $D599 | JSR to WATJOB ($D599) to wait for the write job to be completed. | |
E4F3 | A4 8A | LDY $8A | Load .Y with the pointer from $R4 ($8A) and compare it to $03. If .Y>$03 / there are more side sectors to update so branch back to NS40. | |
E4F5 | C0 03 | CPY #$03 | ||
E4F7 | B0 D8 | BCS $E4D1 | ||
E4F9 | 4C 1E CF | JMP $CF1E | Terminate routine with a JMP to DBLBUF ($CF1E) to reset the active buffer. | |
E4FC | 00 A0 4F CB 20 21 22 23 24 27 D2 45 41 44 89 52 83 20 54 4F 4F 20 4C 41 52 47 C5 50 8B 06 20 50 52 45 53 45 4E D4 51 CF 56 45 52 46 4C 4F 57 20 49 4E 8B 25 28 8A 89 26 8A 20 50 52 4F 54 45 43 54 20 4F CE 29 88 20 49 44 85 30 31 32 33 34 D3 59 4E 54 41 58 89 60 8A 03 84 63 83 20 45 58 49 53 54 D3 64 83 20 54 59 50 45 85 65 CE 4F 20 42 4C 4F 43 CB 66 67 C9 4C 4C 45 47 41 4C 20 54 52 41 43 4B 20 4F 52 20 53 45 43 54 4F D2 61 83 06 84 39 62 83 06 87 01 83 53 20 53 43 52 41 54 43 48 45 C4 70 CE 4F 20 43 48 41 4E 4E 45 CC 71 C4 49 52 89 72 88 20 46 55 4C CC 73 C3 42 4D 20 44 4F 53 20 56 32 2E 36 20 31 35 34 B1 74 C4 52 49 56 45 06 20 52 45 41 44 D9 | Error message table $E4FC - $E5D4Each entry consists of the applicable error numbers followed by the message test with the first and last characters OR'ed with $80. The key words in the text are tokenized (values $80 - $8F). The tokenized word list follows the main error message table.
| ||
E5D5 | 09 C5 52 52 4F D2 0A D7 52 49 54 C5 03 C6 49 4C C5 04 CF 50 45 CE 05 CD 49 53 4D 41 54 43 C8 06 CE 4F D4 07 C6 4F 55 4E C4 08 C4 49 53 CB 0B D2 45 43 4F 52 C4 | Table of tokenized words $E5D5 - $E609
| ||
Handle errors reported by controller
|
||||
ERROR | E60A | 48 | PHA | Save the error code onto the stack. |
E60B | 86 F9 | STX $F9 | Store the job number into JOBNUM ($F9) . | |
E60D | 8A | TXA | Transfer job number (from .X) to .A, multiply it by 2 (ASL). and transfer the result back into .X. | |
E60E | 0A | ASL | ||
E60F | AA | TAX | ||
E610 | B5 06 | LDA $06,X | Set TRACK ($80) and SECTOR ($81) using the values from the last header read in HDRS,X ($06, X) and HDRS+1,X ($07, X). | |
E612 | 85 80 | STA $80 | ||
E614 | B5 07 | LDA $07,X | ||
E616 | 85 81 | STA $81 | ||
E618 | 68 | PLA | Pull the disk controller error code off the stack and convert it into a DOS error code by: | |
E619 | 29 0F | AND #$0F | AND the error code in .A with $0F. If the result is $00, branch to ERR1 to handle error codes $10 - $14. | |
E61B | F0 08 | BEQ $E625 | ||
E61D | C9 0F | CMP #$0F | Compare the result to $0F (no drive) . If the code is NOT $0F, branch to ERR2 . | |
E61F | D0 06 | BNE $E627 | ||
E621 | A9 74 | LDA #$74 | Load .A with $74 (DOS no drive code) and branch to ERR3 (always) . | |
E623 | D0 08 | BNE $E62D | ||
ERR1 | E625 | A9 06 | LDA #$06 | Load .A with $06. |
ERR2 | E627 | 09 20 | ORA #$20 | OR the code in .A with $20 and subtract 2 from the result. |
E629 | AA | TAX | ||
E62A | CA | DEX | ||
E62B | CA | DEX | ||
E62C | 8A | TXA | ||
ERR3 | E62D | 48 | PHA | Save the DOS error code onto the stack. |
E62E | AD 2A 02 | LDA $022A | Compare the command number from CMDNUM ($022A) with $00 to see if this was a VALIDATE command. If not, branch to ERR4 | |
E631 | C9 00 | CMP #$00 | ||
E633 | D0 0F | BNE $E644 | ||
E635 | A9 FF | LDA #$FF | Set CMDNUM ($022A) to $FF. | |
E637 | 8D 2A 02 | STA $022A | ||
E63A | 68 | PLA | Pull the DOS error code off the stack and JSR to ERRMSG ($E6C7) to transfer the error message to the error buffer. | |
E63B | 20 C7 E6 | JSR $E6C7 | ||
E63E | 20 42 D0 | JSR $D042 | JSR to INITDR ($D042) to initialize the drive and eliminate the bad BAM in RAM. | |
E641 | 4C 48 E6 | JMP $E648 | JMP to CMDER3 ($E648) to complete the error handling. | |
ERR4 | E644 | 68 | PLA | Pull the DOS error code off the stack. * |
CMDER2 | E645 | 20 C7 E6 | JSR $E6C7 | JSR to ERRMSG ($E6C7) to transfer the the error message to the error buffer. |
CMDER3 | E648 | 20 BD C1 | JSR $C1BD | JSR to CLRCB ($C1BD) to clear out the command buffer. |
E64B | A9 00 | LDA #$00 | Clear the write-BAM flag, WBAM ($02F9) so a bad copy of the BAM will not be written to disk. | |
E64D | 8D F9 02 | STA $02F9 | ||
E650 | 20 2C C1 | JSR $C12C | JSR to ERRON ($C12C) to start the error LED flashing. | |
E653 | 20 DA D4 | JSR $D4DA | JSR to FREICH ($D4DA) to free the internal read or write channel. | |
E656 | A9 00 | LDA #$00 | Zero BUFTAB+CBPTR ($A3) to clear the pointers . | |
E658 | 85 A3 | STA $A3 | ||
E65A | A2 45 | LDX #$45 | Load .X with $45 (#TOPWRT) and transfer this value to the STACK POINTER to purge the stack | |
E65C | 9A | TXS | ||
E65D | A5 84 | LDA $84 | Load .A with the original secondary address from ORGSA ($84). AND it with $0F, and store the result as the current secondary address in SA ($83). | |
E65F | 29 0F | AND #$0F | ||
E661 | 85 83 | STA $83 | ||
E663 | C9 0F | CMP #$0F | Compare the secondary address (in .A) with $0F. If it is $0F (the command channel), branch to ERR10. | |
E665 | F0 31 | BEQ $E698 | ||
E667 | 78 | SEI | Set the interrupt flag to prevent any interrupts ! | |
E668 | A5 79 | LDA $79 | If the listener active flag in LSNACT ($79) is not $00, we are an active listener so branch to LSNERR. | |
E66A | D0 1C | BNE $E688 | ||
E66C | A5 7A | LDA $7A | If the talker active flag in TLKACT ($7A) is not $00, we are an active talker so branch to TLKERR. | |
E66E | D0 10 | BNE $E680 | ||
E670 | A6 83 | LDX $83 | Load .X with the current secondary address from SA ($83) . | |
E672 | BD 2B 02 | LDA $022B,X | Load .A with the active channel number from LINTAB,X ($022B / X). If this channel number is $FF, the channel is inactive so branch to ERR10. | |
E675 | C9 FF | CMP #$FF | ||
E677 | F0 1F | BEQ $E698 | ||
E679 | 29 0F | AND #$0F | AND the channel number (in .A) with $0F, store it as the current channel number in LINDX ($82) and JMP to TLERR ($E68E). | |
E67B | 85 82 | STA $82 | ||
E67D | 4C 8E E6 | JMP $E68E | ||
Talker error recoveryRelease all bus lines and go idle. |
||||
TLKERR | E680 | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. |
E683 | 20 4E EA | JSR $EA4E | JSR to ITERR ($EA4E) to release all bus lines and JMP to IDLE ($EBE7) . | |
E686 | D0 06 | BNE $E68E | ||
Listener error recoveryRelease all bus lines and go idle. |
||||
LSNERR | E688 | 20 07 D1 | JSR $D107 | JSR to FNDRCH ($D0EB) to find an unused read channel. |
E68B | 20 4E EA | JSR $EA4E | JSR to ITERR ($EA4E) to release all bus lines and JMP to IDLE ($EBE7) . | |
TLERR | E68E | 20 25 D1 | JSR $D125 | Unused on the 1541 |
E691 | C9 04 | CMP #$04 | ||
E693 | B0 03 | BCS $E698 | ||
E695 | 20 27 D2 | JSR $D227 | ||
ERR10 | E698 | 4C E7 EB | JMP $EBE7 | Terminate routine with a JMP to IDLE ($EBE7) . |
Convert hex to BCD
|
||||
HEXDEC | E69B | AA | TAX | Transfer hex from .A to .X. |
E69C | A9 00 | LDA #$00 | Zero .A and set decimal mode (SED) . | |
E69E | F8 | SED | ||
HEX0 | E69F | E0 00 | CPX #$00 | Compare .X value to $00. If equal, branch to HEX5 to exit. |
E6A1 | F0 07 | BEQ $E6AA | ||
E6A3 | 18 | CLC | Clear carry flag, add 1 to value in .A decrement .X, and JMP backto HEX0. | |
E6A4 | 69 01 | ADC #$01 | ||
E6A6 | CA | DEX | ||
E6A7 | 4C 9F E6 | JMP $E69F | ||
HEX5 | E6AA | D8 | CLD | Clear decimal mode (CLD) . |
Convert BCD to ASCII decimal digit
|
||||
BCDDEC | E6AB | AA | TAX | Transfer BCD from .A to .X. |
E6AC | 4A | LSR | Divide BCD value in .X by 16 (4 x LSR) | |
E6AD | 4A | LSR | ||
E6AE | 4A | LSR | ||
E6AF | 4A | LSR | ||
E6B0 | 20 B4 E6 | JSR $E6B4 | JSR to BCD2 ($E6B4) to convert the most significant digit to ASCII. | |
E6B3 | 8A | TXA | Transfer original BCD byte from .X to .A | |
BCD2 | E6B4 | 29 0F | AND #$0F | AND the BCD value in .A with $0F to mask off the higher order nybble, OR the result with $30 (convert to ASCII), and store the ASCII value in (CB+2)Y; ($A5)Y |
E6B6 | 09 30 | ORA #$30 | ||
E6B8 | 91 A5 | STA ($A5),Y | ||
E6BA | C8 | INY | Increment .Y | |
E6BB | 60 | RTS | Terminate routine with an RTS. | |
Transfer error message to error buffer |
||||
OKERR | E6BC | 20 23 C1 | JSR $C123 | JSR to ERROFF ($C123) to turn off error LED. |
E6BF | A9 00 | LDA #$00 | Load .A with $00 (no error) . | |
ERRTSO | E6C1 | A0 00 | LDY #$00 | Set TRACK ($80) and SECTOR ($81) to $00. |
E6C3 | 84 80 | STY $80 | ||
E6C5 | 84 81 | STY $81 | ||
ERRMSG | E6C7 | A0 00 | LDY #$00 | Load .Y with $00. |
E6C9 | A2 D5 | LDX #$D5 | Set pointer at CB+2/3 ($A5/6) to point to the error buffer ($02D5). | |
E6CB | 86 A5 | STX $A5 | ||
E6CD | A2 02 | LDX #$02 | ||
E6CF | 86 A6 | STX $A6 | ||
E6D1 | 20 AB E6 | JSR $E6AB | JSR to BCDDEC ($E6AB) to convert the BCD number in .A to ASCII and store it at the start of the error buffer. | |
E6D4 | A9 2C | LDA #$2C | Store $2C ". " after the error code in the error buffer (CB+2) ,Y; ($A5) ,Y. | |
E6D6 | 91 A5 | STA ($A5),Y | ||
E6D8 | C8 | INY | Increment .Y (points into error buffer) . | |
E6D9 | AD D5 02 | LDA $02D5 | Copy the first character of the error buffer from ERRBUF ($02D5) into the channel data area CHNDAT+ERRCHN ($0243). | |
E6DC | 8D 43 02 | STA $0243 | ||
E6DF | 8A | TXA | Transfer the error number from .X to .A and JSR to ERMOVE ($E706) to move the error message into the error buffer. | |
E6E0 | 20 06 E7 | JSR $E706 | ||
E6E3 | A9 2C | LDA #$2C | Store $2C ". " after the error message in the error buffer (CB+2),Y; ($A5),Y. | |
E6E5 | 91 A5 | STA ($A5),Y | ||
E6E7 | C8 | INY | Increment .Y (points into error buffer) . | |
E6E8 | A5 80 | LDA $80 | Load .A with the track number from TRACK ($80) . | |
E6EA | 20 9B E6 | JSR $E69B | JSR to BCDDEC ($E6AB) to convert the track number in .A to ASCII and store it in the error buffer. | |
E6ED | A9 2C | LDA #$2C | Store $2C ". " after the track number in the error buffer (CB+2),Y; ($A5),Y. | |
E6EF | 91 A5 | STA ($A5),Y | ||
E6F1 | C8 | INY | Increment .Y (points into error buffer) . | |
E6F2 | A5 81 | LDA $81 | Load .A with the sector number from SECTOR ($81) . | |
E6F4 | 20 9B E6 | JSR $E69B | JSR to BCDDEC ($E6AB) to convert the sector number in .A to ASCII and store it in the error buffer. | |
E6F7 | 88 | DEY | Decrement the .Y pointer by 1, transfer the result to .A, clear the carry flag, add $D5 (the start of the error buffer) , and store the final result (points to the last character) into LSTCHR+ERRCHN ($0249) . | |
E6F8 | 98 | TYA | ||
E6F9 | 18 | CLC | ||
E6FA | 69 D5 | ADC #$D5 | ||
E6FC | 8D 49 02 | STA $0249 | ||
E6FF | E6 A5 | INC $A5 | Increment the lo byte of the pointer in CB+2 ($A5) by 1 so it points to the second character of the message (we put the first character into the channel data area already. | |
E701 | A9 88 | LDA #$88 | Set error channel status CHNRDY+ERRCHN ($F7) to $88 to indicate that it is ready-to-talk. | |
E703 | 85 F7 | STA $F7 | ||
E705 | 60 | RTS | Terminate routine with an RTS. | |
Move the error message from the error table to the error bufferThe tokens in the table are converted to words |
||||
ERMOVE | E706 | AA | TAX | Transfer the error message number from .A to .X. |
E707 | A5 86 | LDA $86 | Save the current values of R0 ($86) and R0+1 ($87) onto the stack so we can use this as a temporary pointer. | |
E709 | 48 | PHA | ||
E70A | A5 87 | LDA $87 | ||
E70C | 48 | PHA | ||
E70D | A9 FC | LDA #$FC | Set up a pointer in R0/R0+1 to point to the error message table in ROM ($E4FC) . | |
E70F | 85 86 | STA $86 | ||
E711 | A9 E4 | LDA #$E4 | ||
E713 | 85 87 | STA $87 | ||
E715 | 8A | TXA | Transfer the error number back into .A. | |
E716 | A2 00 | LDX #$00 | Zero .X to use as an indirect pointer. | |
E10 | E718 | C1 86 | CMP ($86,X) | Compare the error number (in .A) with the error number in the table (R0,X) ($86, X). If a match is found, branch to E50. |
E71A | F0 21 | BEQ $E73D | ||
E71C | 48 | PHA | Save error number onto the stack. | |
E71D | 20 75 E7 | JSR $E775 | JSR to EADV2 ($E775) to advance the pointer to the error table. | |
E720 | 90 05 | BCC $E727 | If carry flag is clear, there are more messages to check so branch to E30 | |
E20 | E722 | 20 75 E7 | JSR $E775 | No more messages so JSR to EADV2 ($E775) to advance the pointer. |
E725 | 90 FB | BCC $E722 | If carry flag is clear, we are not done with the message yet so branch to E20. | |
E30 | E727 | A5 87 | LDA $87 | Compare the hi byte of the pointer in R0+1 ($87) to $E6. If the pointer is less than $E6, there is more table left so branch to E40. If the pointer is greater then $E6, we are past the end the table so branch to E45. |
E729 | C9 E6 | CMP #$E6 | ||
E72B | 90 08 | BCC $E735 | ||
E72D | D0 0A | BNE $E739 | ||
E72F | A9 0A | LDA #$0A | The hi bytes match so compare the lo bytes of the pointer in R0 ($86) with $0A (the end of the table). If we are past the end, branch to E45. | |
E731 | C5 86 | CMP $86 | ||
E733 | 90 04 | BCC $E739 | ||
E40 | E735 | 68 | PLA | Pull the error number off the stack and JMP to E10 to continue checking. |
E736 | 4C 18 E7 | JMP $E718 | ||
E45 | E739 | 68 | PLA | Can't find error number in table so pop the error number off the stack and JMP to E90 ($E74D) to quit. |
E73A | 4C 4D E7 | JMP $E74D | ||
E50 | E73D | 20 67 E7 | JSR $E767 | The error number has been located so JSR to EADV1 ($E767) to advance past the other error numbers. |
E740 | 90 FB | BCC $E73D | If carry flag is clear, we have not- advanced far enough so branch to E50. | |
E55 | E742 | 20 54 E7 | JSR $E754 | JSR to E60 ($E754) to check for token and put character (s) into buffer. |
E745 | 20 67 E7 | JSR $E767 | JSR to EADV1 ($E767) to advance pointer. | |
E748 | 90 F8 | BCC $E742 | If carry flag is clear, there is more to do so branch back to E55. | |
E74A | 20 54 E7 | JSR $E754 | JSR to E60 ($E754) to check for token or last word. | |
E90 | E74D | 68 | PLA | All done! Pull original RO and RO+1 values off the stack and replace them. |
E74E | 85 87 | STA $87 | ||
E750 | 68 | PLA | ||
E751 | 85 86 | STA $86 | ||
E753 | 60 | RTS | Terminate routine with an RTS. | |
Sub to check for token or word and put it into the buffer. |
||||
E60 | E754 | C9 20 | CMP #$20 | Compare the character in .A with $20 (the maximum token number +1). If .A is greater, this is not a token so branch to E70. |
E756 | B0 0B | BCS $E763 | ||
E758 | AA | TAX | Save token (in .A) into .X. | |
E759 | A9 20 | LDA #$20 | Store $20 (implied leading space) into the buffer at (CB+2),Y; ($A5),Y. | |
E75B | 91 A5 | STA ($A5),Y | ||
E75D | C8 | INY | Increment .Y. | |
E75E | 8A | TXA | Move the token from .X back into .A. | |
E75F | 20 06 E7 | JSR $E706 | JSR to ERMOVE ($E706) to add the token word to the message. | |
E762 | 60 | RTS | Terminate routine with an RTS. | |
E70 | E763 | 91 A5 | STA ($A5),Y | Store character (in .A) into the buffer at. (CB + 2) ,Y; ($A5) ,Y. |
E765 | C8 | INY | Increment .Y pointer into error buffer. | |
E766 | 60 | RTS | Terminate routine with an RTS. | |
Advance error pointer before move |
||||
EADV1 | E767 | E6 86 | INC $86 | Increment the lo byte of the pointer in RO ($86). If the new value is not $00, branch to EA10. |
E769 | D0 02 | BNE $E76D | ||
E76B | E6 87 | INC $87 | Increment the hi byte of the pointer in RO+1 ($87). | |
EA10 | E76D | A1 86 | LDA ($86,X) | Load .A with the next character from the error message table (R0,X); ($A1,X). |
E76F | 0A | ASL | Shift the byte in .A left to set the carry flag if this is the first or last character in the message. | |
E770 | A1 86 | LDA ($86,X) | Load .A with the next character from the error message table (R0,X); ($A1,X), | |
E772 | 29 7F | AND #$7F | AND the character in .A with $7F to mask off bit 7. | |
E774 | 60 | RTS | Terminate routine with an RTS. | |
Advance error pointer after move |
||||
EADV2 | E775 | 20 6D E7 | JSR $E76D | JSR to EA10 ($E76D) to get the next byte from the error message table. |
E778 | E6 86 | INC $86 | Increment the lo byte of the pointer in RO ($86). If the new value is not $00, branch to EA20. | |
E77A | D0 02 | BNE $E77E | ||
E77C | E6 87 | INC $87 | Increment the hi byte of the pointer in R0+1 ($87) . | |
EA20 | E77E | 60 | RTS | Terminate routine with an RTS. |
Utility loader programThis utility is used to load and execute user proarams or system utilities from disk. This utility may be used in two ways: a) On power-up: If the data and clock lines are grounded at power up, the routine is entered. It waits until the ground clip is removed and then loads the first file found in the directory into disk RAM using the first two bytes of the file as the load address. Once the file is loaded, it is executed starting at the first byte. b) Normal entry: The disk command "&: filename" will load and execute the file whose filename is specified. For examole: PRINT#15,"&0:DISK TASK" |
||||
File structure:The utility or program must be of the following form.
|
||||
|
||||
BOOT2 | E77F | 60 | RTS | Exit routine with an RTS. |
BOOT | E780 | AD 00 18 | LDA $1800 | Load .A with input port data from PB ($1800). Transfer data from .A to .X. |
E783 | AA | TAX | ||
E784 | 29 04 | AND #$04 | AND the data byte (in .A) with $04 to see if clock is grounded. If not, branch to BOOT2 to exit. | |
E786 | F0 F7 | BEQ $E77F | ||
E788 | 8A | TXA | Transfer data byte from .X to .A. | |
E789 | 29 01 | AND #$01 | AND the data byte (in .A) with $01 to see if data line is grounded. If not, branch to BOOT2 to exit. | |
E78B | F0 F2 | BEQ $E77F | ||
E78D | 58 | CLI | Clear interrupt flag so that background routines will run. | |
Boot clip must be on! |
||||
BOOT3 | E78E | AD 00 18 | LDA $1800 | Load .A with input port data from PB ($1800) . |
E791 | 29 05 | AND #$05 | AND the data byte (in .A) with $05 to see if clip has been removed. If not, branch to BOOT3 to wait until it is. | |
E793 | D0 F9 | BNE $E78E | ||
E795 | EE 78 02 | INC $0278 | Set the number of files to $01 by incrementing F2CNT ($0278). | |
E798 | EE 74 02 | INC $0274 | Set the command string length to $01 by incrementing CMDSIZ ($0274). | |
E79B | A9 2A | LDA #$2A | Set the first character in the command buffer, CMDBUF ($0200), to $2A ("*") to match any file name. | |
E79D | 8D 00 02 | STA $0200 | ||
E7A0 | 4C A8 E7 | JMP $E7A8 | JMP to BOOT4 ($E7A8) to continue. | |
Normal entry point |
||||
UTLODR | E7A3 | A9 8D | LDA #$8D | Load .A with $8D and JSR to PARSE ($C268) to parse the command string. |
E7A5 | 20 68 C2 | JSR $C268 | ||
BOOT4 | E7A8 | 20 58 F2 | JSR $F258 | JSR to KILLP ($F258) to kill protect. Does nothing on the 15 41! |
E7AB | AD 78 02 | LDA $0278 | Load .A with the file count from F2CNT ($0278) and save it on the stack. | |
E7AE | 48 | PHA | ||
E7AF | A9 01 | LDA #$01 | Set file count in F2CNT ($0278) to $01. | |
E7B1 | 8D 78 02 | STA $0278 | ||
E7B4 | A9 FF | LDA #$FF | Set first-byte flag in R0 ($86) to $FF. | |
E7B6 | 85 86 | STA $86 | ||
E7B8 | 20 4F C4 | JSR $C44F | JSR to LOOKUP($C44F) to locate the file name on the disk. | |
E7BB | AD 80 02 | LDA $0280 | Check the track link for the file found in FILTRK ($0280). If it is $00, the file was not found so branch to UTLDOO. | |
E7BE | D0 05 | BNE $E7C5 | ||
E7C0 | A9 39 | LDA #$39 | Load .A with $39 to indicate a FILE NOT FOUND error and JSR to CMDERR ($C1C8) to exit. | |
E7C2 | 20 C8 C1 | JSR $C1C8 | ||
UTLD00 | E7C5 | 68 | PLA | Pull original file count off the stack and restore it into F2CNT ($0278) . |
E7C6 | 8D 78 02 | STA $0278 | ||
E7C9 | AD 80 02 | LDA $0280 | Set TRACK ($80) from the track link for the file from FILTRK ($0280) . | |
E7CC | 85 80 | STA $80 | ||
E7CE | AD 85 02 | LDA $0285 | Set SECTOR ($81) from the sector link for the file from FILSEC ($0285) . | |
E7D1 | 85 81 | STA $81 | ||
E7D3 | A9 03 | LDA #$03 | Load .A with $03 (USER FILE TYPE) and JSR to OPNTYP ($D477) to open the file. | |
E7D5 | 20 77 D4 | JSR $D477 | ||
UTLD10 | E7D8 | A9 00 | LDA #$00 | Load .A with $00 and store it in Rl($87) to initialize the checksum. |
E7DA | 85 87 | STA $87 | ||
E7DC | 20 39 E8 | JSR $E839 | JSR to GTABYT ($E839) to get the first byte from the file (lo of load address), | |
E7DF | 85 88 | STA $88 | Store the lo byte of the load address in R2 ($88) . | |
E7E1 | 20 4B E8 | JSR $E84B | JSR to ADDSUM ($E84B) to add the byte into the checksum. | |
E7E4 | 20 39 E8 | JSR $E839 | JSR to GTABYT ($E839) to get the second byte from the file (hi of load address) . | |
E7E7 | 85 89 | STA $89 | Store the hi byte of the load address in R3 ($89) . | |
E7E9 | 20 4B E8 | JSR $E84B | JSR to ADDSUM ($E84B) to add the byte into the checksum. | |
E7EC | A5 86 | LDA $86 | Load .A with the flag from RO ($86). If the flag is $00, this is not the load address so branch to UTLD20. | |
E7EE | F0 0A | BEQ $E7FA | ||
E7F0 | A5 88 | LDA $88 | Load lo byte of load address from R2 ($88) and save it onto the stack. | |
E7F2 | 48 | PHA | ||
E7F3 | A5 89 | LDA $89 | Load hi byte of load address from R3 ($89) and save it onto the stack. | |
E7F5 | 48 | PHA | ||
E7F6 | A9 00 | LDA #$00 | Set first-byte flag in RO ($86) to $00. | |
E7F8 | 85 86 | STA $86 | ||
UTLD20 | E7FA | 20 39 E8 | JSR $E839 | JSR to GTABYT ($E839) to get the data byte count from the file. |
E7FD | 85 8A | STA $8A | Store the data byte count in R4 ($8A) . | |
E7FF | 20 4B E8 | JSR $E84B | JSR to ADDSUM ($E84B) to add the byte into the checksum. | |
UTLD30 | E802 | 20 39 E8 | JSR $E839 | JSR to GTABYT ($E839) to get a data byte from the file. |
E805 | A0 00 | LDY #$00 | Zero .Y and store the data byte (in .A) at desired address, (R2),Y; ($88), Y. | |
E807 | 91 88 | STA ($88),Y | ||
E809 | 20 4B E8 | JSR $E84B | JSR to ADDSUM ($E84B) to add the byte into the checksum. | |
E80C | A5 88 | LDA $88 | Increment the lo byte of the pointer in R2 ($88) by $01. If the result is not $00, branch to UTLD35. | |
E80E | 18 | CLC | ||
E80F | 69 01 | ADC #$01 | ||
E811 | 85 88 | STA $88 | ||
E813 | 90 02 | BCC $E817 | Increment the hi byte of the pointer in R3 ($89) by $01. | |
E815 | E6 89 | INC $89 | ||
UTLD35 | E817 | C6 8A | DEC $8A | Decrement the byte counter in R4 ($8A) . If the result is not $00, there are more bytes to get so branch back to UTLD30. |
E819 | D0 E7 | BNE $E802 | ||
E81B | 20 35 CA | JSR $CA35 | JSR to GIBYTE ($CA35) to get a data byte from the file without an EOI check. | |
E81E | A5 85 | LDA $85 | Load .A with the checksum from DATA ($85) and compare it with the computed check- sum in Rl ($87), If they match, all is OK so branch to UTLD50. | |
E820 | C5 87 | CMP $87 | ||
E822 | F0 08 | BEQ $E82C | ||
E824 | 20 3E DE | JSR $DE3E | Bad checksum so JSR to GETHDR ($DE3E) to set TRACK and SECTOR from the header. | |
E827 | A9 50 | LDA #$50 | Load .A with $50 to indicate a NO RECORD error and JSR to CMDER2 ($E645). | |
E829 | 20 45 E6 | JSR $E645 | ||
UTLD50 | E82C | A5 F8 | LDA $F8 | Load .A with the EOI flag from EIOFLG ($F8). If the flag is NOT $00, we are not done yet so branch back to UTLD10 to do another 256 bytes. |
E82E | D0 A8 | BNE $E7D8 | ||
E830 | 68 | PLA | Routine all loaded so pull load address off the stack (lo/hi), set up a jump vector in R2/3 ($88/9). and do an indirect JMP to the routine via (R2) . | |
E831 | 85 89 | STA $89 | ||
E833 | 68 | PLA | ||
E834 | 85 88 | STA $88 | ||
E836 | 6C 88 00 | JMP ($0088) | ||
Subroutines for UTLODR |
||||
GTABYT | E839 | 20 35 CA | JSR $CA35 | Get a byte from the file opened using the internal read channel. There is an end-of-file check done. If EOI occurs, a #51 DOS error is reported. JSR to GIBYTE ($CA35) to fetch a byte and store it in DATA ($85) . |
E83C | A5 F8 | LDA $F8 | Test the end of information flag, EOIFLG ($F8). If NOT $00, we have not come to the end so branch to GTABYE. | |
E83E | D0 08 | BNE $E848 | ||
E840 | 20 3E DE | JSR $DE3E | We have an EOI condition. JSR to GETHDR ($DE3E) to set TRACK and SECTOR from the header. | |
E843 | A9 51 | LDA #$51 | Load .A with $51 to indicate a RECORD SIZE error and JSR to CMDER2 ($E645). | |
E845 | 20 45 E6 | JSR $E645 | ||
GTABYE | E848 | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) |
E84A | 60 | RTS | Terminate routine with an RTS. | |
Compute the running checksum in R1On entry: .A = new byte to add |
||||
ADDSUM | E84B | 18 | CLC | Clear the carry flag. |
E84C | 65 87 | ADC $87 | Add the byte in R1 ($8 7) to the byte in .A and then add $00 to the result to add in the carry bit. | |
E84E | 69 00 | ADC #$00 | ||
E850 | 85 87 | STA $87 | Store the new checksum into Rl. | |
E852 | 60 | RTS | Terminate routine with an RTS. | |
Serial bus communication routinesEntry point for irq routine to service attention (ATN) signals from the C-64. |
||||
ATNIRQ | E853 | AD 01 18 | LDA $1801 | Load .A with the contents of PA1 ($1801) to clear the interrupt (IRQ) flag (CA1). |
E856 | A9 01 | LDA #$01 | Store $01 in ATNPND ($7C) to indicate that an ATN request is pending. | |
E858 | 85 7C | STA $7C | ||
E85A | 60 | RTS | Terminate routine with an RTS. | |
Service the attention request from the C-64. |
||||
ATNSRV | E85B | 78 | SEI | Set the interrupt flag (SEI) to prevent any interrupts. |
E85C | A9 00 | LDA #$00 | Store $00 in ATNPND ($7C) to indicate that no ATN request is pending. | |
E85E | 85 7C | STA $7C | ||
E860 | 85 79 | STA $79 | Zero the listener and talker active flags LSNACT ($79) and TLKACT ($7A). | |
E862 | 85 7A | STA $7A | ||
E864 | A2 45 | LDX #$45 | Load .X with $45 and transfer this value to the stack pointer to reset the stack. | |
E866 | 9A | TXS | ||
E867 | A9 80 | LDA #$80 | Store $80 in the EOI flag, EOIFLG ($F8) to indicate a non-EOI state. | |
E869 | 85 F8 | STA $F8 | ||
E86B | 85 7D | STA $7D | Store $80 in the ATN mode flag, ATNMOD ($7D) to set ATN mode for ACPT routine | |
E86D | 20 B7 E9 | JSR $E9B7 | JSR to CLKHI ($E9B7) to wait for the clock line go high. | |
E870 | 20 A5 E9 | JSR $E9A5 | JSR to DATLOW ($E9A5) to set the data line low as a response. | |
E873 | AD 00 18 | LDA $1800 | To get hardware control of the data line acknowledge the attention signal by: loading .A with the contents of port B, PB ($1800), OR the byte with $10 to set the ACK ATN bit, and store the result- back into port B, PB ($1800) . | |
E876 | 09 10 | ORA #$10 | ||
E878 | 8D 00 18 | STA $1800 | ||
ATNS15 | E87B | AD 00 18 | LDA $1800 | Check to see if the ATN signal is still present, by: loading .A with the contents of port B, PB ($1800). If bit 7 is not set, the ATN signal is gone so branch to ATNS20 ($E8D7) . |
E87E | 10 57 | BPL $E8D7 | ||
E880 | 29 04 | AND #$04 | AND the contents of .A with $04 to see if the clock line is still low. If bit 2 is set (result of AND is not $00). the clock line is still low so branch back to ATNS15 to wait. | |
E882 | D0 F7 | BNE $E87B | ||
E884 | 20 C9 E9 | JSR $E9C9 | Clock line went high so there is a command byte waiting for us. JSR to ACPTR (SE9C9) to get the command byte. | |
E887 | C9 3F | CMP #$3F | Compare the command byte (in .A) with $3F (unlisten). If this is not an unlisten command, branch to ATN35. | |
E889 | D0 06 | BNE $E891 | ||
E88B | A9 00 | LDA #$00 | General unlisten command received. Zero the listener active flag, LSNACT ($7A) and branch to ATN122 ($E902). | |
E88D | 85 79 | STA $79 | ||
E88F | F0 71 | BEQ $E902 | ||
ATN35 | E891 | C9 5F | CMP #$5F | Compare the command byte (in .A) with $5F (untalk). If this is not an untalk command, branch to ATN40. |
E893 | D0 06 | BNE $E89B | ||
E895 | A9 00 | LDA #$00 | General untalk command received. Zero the talker active flag, TLKACT ($7A) and branch to ATN122 ($E902). | |
E897 | 85 7A | STA $7A | ||
E899 | F0 67 | BEQ $E902 | ||
ATN40 | E89B | C5 78 | CMP $78 | Compare the command byte (in .A) with our talk address in TLKADR ($78). If this is not our talk address, branch to ATN45. |
E89D | D0 0A | BNE $E8A9 | ||
E89F | A9 01 | LDA #$01 | Talk command for us. Set the talker active flag, TLKACT ($7A) to $01, the listener active flag, LSNACT ($79) to $00, and branch to ATN95. | |
E8A1 | 85 7A | STA $7A | ||
E8A3 | A9 00 | LDA #$00 | ||
E8A5 | 85 79 | STA $79 | ||
E8A7 | F0 29 | BEQ $E8D2 | ||
ATN45 | E8A9 | C5 77 | CMP $77 | Compare the command byte (in .A) with our listen address in LSNADR ($77). If this is not our listen address, branch to ATN5 0. |
E8AB | D0 0A | BNE $E8B7 | ||
E8AD | A9 01 | LDA #$01 | Listen command for us. Set the listener active flag, LSNACT ($79) to $01, the talker active flag, TLKACT ($7A) to $00, and branch to ATN95 | |
E8AF | 85 79 | STA $79 | ||
E8B1 | A9 00 | LDA #$00 | ||
E8B3 | 85 7A | STA $7A | ||
E8B5 | F0 1B | BEQ $E8D2 | ||
ATN50 | E8B7 | AA | TAX | Save the command byte by transferring it from .A to .X. |
E8B8 | 29 60 | AND #$60 | Test if the command byte is a secondary address by AND'ing it with $60. If the result is not $60, this is not a secondary address so branch to ATN120. NCTE: SA = $60 + N A secondary address for the drive. | |
E8BA | C9 60 | CMP #$60 | ||
E8BC | D0 3F | BNE $E8FD | ||
E8BE | 8A | TXA | Transfer the original command byte from .X back into .A. | |
E8BF | 85 84 | STA $84 | Store the original secondary address byte into ORGSA ($84). | |
E8C1 | 29 0F | AND #$0F | AND the secondary address (in .A) with $0F to strip off any junk and store the result as the current secondary address in SA ($83) . Test if this is a CLOSE command for this secondary address . | |
E8C3 | 85 83 | STA $83 | ||
E8C5 | A5 84 | LDA $84 | Load .A with the original secondary address from ORGSA ($84). AND this value with $F0 to mask off the low nybble. If the result is not $E0, this is not a CLOSE command so branch to ATN122. CLOSE the file with this SA. | |
E8C7 | 29 F0 | AND #$F0 | ||
E8C9 | C9 E0 | CMP #$E0 | ||
E8CB | D0 35 | BNE $E902 | ||
E8CD | 58 | CLI | Clear the interrupt flag (CLI) to enable interrupts . | |
E8CE | 20 C0 DA | JSR $DAC0 | JSR to CLOSE ($DAC0) to close the file. | |
|
||||
E8D1 | 78 | SEI | Set the interrupt flag (SEI) to prevent any interrupts. | |
ATN95 | E8D2 | 2C 00 18 | BIT $1800 | Test if the ATN signal is still present. If it is, branch back to ATN30. ATN SIGNAL GONE - CARRY OUT COMMAND |
E8D5 | 30 AD | BMI $E884 | ||
ATSN20 | E8D7 | A9 00 | LDA #$00 | Store $00 in ATNMOD ($7D) to clear the attention mode. |
E8D9 | 85 7D | STA $7D | ||
E8DB | AD 00 18 | LDA $1800 | Release the ATN ACK line by loading the byte from port B, PB ($1800), AND'ing it with $EF ($FF-ATNA), and storing the result back into port B ($1800) . | |
E8DE | 29 EF | AND #$EF | ||
E8E0 | 8D 00 18 | STA $1800 | ||
E8E3 | A5 79 | LDA $79 | Test the listener active flag, LSNACT ($79) to se if we are supposed to be a listener. If flag is $00, branch to ATN100 | |
E8E5 | F0 06 | BEQ $E8ED | ||
BE AN ACTIVE TALKER. |
||||
E8E7 | 20 2E EA | JSR $EA2E | JSR to DATHI ($E99C) to free data line, serial bus. | |
E8EA | 4C E7 EB | JMP $EBE7 | JMP to IDLE ($EBE7) . | |
ATN100 | E8ED | A5 7A | LDA $7A | Test the talker active flag, TLKACT($7A) to see if we are supposed to talk. If flag is $00, branch to ATN110. |
E8EF | F0 09 | BEQ $E8FA | ||
BE AN ACTIVE TALKER. |
||||
E8F1 | 20 9C E9 | JSR $E99C | JSR to DATHI ($E99C) to free data line. | |
E8F4 | 20 AE E9 | JSR $E9AE | JSR to CLKLOW ($E9AE) to pull clock low. | |
E8F7 | 20 09 E9 | JSR $E909 | JSR to TALK ($E909) to talk on the bus. | |
ATN110 | E8FA | 4C 4E EA | JMP $EA4E | JMP to ILERR ($EA4E) to release all the lines and shift to idle mode. |
FIX SO DEVICE NOT PRESENT IS REPORTED |
||||
ATN120 | E8FD | A9 10 | LDA #$10 | Store $10 in PB ($1800) to kill all the lines except ATN ACK (ATN ACKnowledge) . |
E8FF | 8D 00 18 | STA $1800 | ||
ATN122 | E902 | 2C 00 18 | BIT $1800 | Test if ATN signal is still present (bit 7 of PB set). If gone, branch to ATSN20. If still present, loop to ATN122. |
E905 | 10 D0 | BPL $E8D7 | ||
E907 | 30 F9 | BMI $E902 | ||
Serial bus talk routines |
||||
TALK | E909 | 78 | SEI | Set the interrupt flag (SEI) to prevent any interrupts. |
E90A | 20 EB D0 | JSR $D0EB | JSR to FNDRCH ($D0EB) to find an unused read channel. If no channel is available branch to NOTLK to exit. | |
E90D | B0 06 | BCS $E915 | ||
TALK1 | E90F | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . |
E911 | B5 F2 | LDA $F2,X | Load .A with the channel status from CHNRDY,X ($F2,X). If bit 7 is set, the status is OK so branch to TLK05. | |
E913 | 30 01 | BMI $E916 | ||
NOTLK | E915 | 60 | RTS | Terminate routine with an RTS. |
Note: CODE ADDED TO FIX VERIFY ERROR |
||||
TLK05 | E916 | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. |
E919 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the clock signal is gone. NOTE: this must be 80 microseconds or more from JMP TALK1. | |
E91C | 29 01 | AND #$01 | AND the data byte in .A with $01 and save it on the stack. | |
E91E | 08 | PHP | ||
E91F | 20 B7 E9 | JSR $E9B7 | JSR to CLKHI ($E9B7) to set the clock line high. | |
E922 | 28 | PLP | Pull the test byte off the stack. If it is $00, this is a VERIFY ERROR so branch to TLK02 to send an EOI . | |
E923 | F0 12 | BEQ $E937 | ||
TALK2 | E925 | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. |
E928 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the data line has been set low. | |
E92B | 29 01 | AND #$01 | AND the test byte (in .A) with $01. If the result is not $00, the line has not been set hi (no response) so branch back to TALK2 to wait for response. | |
E92D | D0 F6 | BNE $E925 | ||
E92F | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . | |
E931 | B5 F2 | LDA $F2,X | Load .A with the channel status from CHNRDY,X ($F2,X), and AND it with $08 to test if we have an EOI condition. If the result is not $00, we do not have an EOI so branch to NOEOI ($E94B) . | |
E933 | 29 08 | AND #$08 | ||
E935 | D0 14 | BNE $E94B | ||
Send an EOI signal to the C-64 by: |
||||
TLK02 | E937 | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. |
E93A | 20 C0 E9 | JSR $E9C0 | JSR to" DEBNC ($E9C0) to send an EOI and test if the data line has been set. | |
E93D | 29 01 | AND #$01 | AND the test byte (in .A) with $01. If the result is not $00, the line has not been set hi (no response) so branch back to TLK02 to wait for hi response. | |
E93F | D0 F6 | BNE $E937 | ||
TLK03 | E941 | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. |
E944 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the data line has been set. | |
E947 | 29 01 | AND #$01 | AND the test byte (in .A) with $01. If the result equals $00, the line has not been set lo (no response) so branch back to TLK02 to wait for lo response. | |
E949 | F0 F6 | BEQ $E941 | ||
NOEOI | E94B | 20 AE E9 | JSR $E9AE | JSR to CLKLOW ($E9AE) to set the clock line low. |
E94E | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. | |
E951 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the data line has been set. | |
E954 | 29 01 | AND #$01 | AND the test byte (in .A) with $01. If the result is not $00, the line has not been set hi (no response) so branch back to NOEOI to wait for hi response. | |
E956 | D0 F3 | BNE $E94B | ||
E958 | A9 08 | LDA #$08 | Store $08 in CONT ($98) to set up the bit counter. | |
E95A | 85 98 | STA $98 | ||
ISR01 | E95C | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to let the port settle. |
E95F | 29 01 | AND #$01 | AND the test byte (in .A) with $01 to be sure the line is hi before we send. If the result is not $00, the line has not been set hi (no response) so branch to FRMFRX($E999) to wait for hi response | |
E961 | D0 36 | BNE $E999 | ||
ISR02 | E963 | A6 82 | LDX $82 | Load .X with the current channel number from LINDX ($82) . |
E965 | BD 3E 02 | LDA $023E,X | Load .A with the channel data byte from CHNDAT,X ($F2,X). Rotate the status byte one bit right (ROR) and store the result back into CHNDAT,X ($F2,X). | |
E968 | 6A | ROR | ||
E969 | 9D 3E 02 | STA $023E,X | ||
E96C | B0 05 | BCS $E973 | If the carry bit is set, branch to ISRHI to send a 1. | |
E96E | 20 A5 E9 | JSR $E9A5 | JSR to DATLOW ($E9A5) to send a 0. | |
E971 | D0 03 | BNE $E976 | Branch to ISRCLK to clock it. | |
ISRHI | E973 | 20 9C E9 | JSR $E99C | JSR to DATHI ($E99C) to send a 1. |
ISRCLK | E976 | 20 B7 E9 | JSR $E9B7 | JSR to CLKHI ($E9B7) to set the clock line hi. (rising edge). |
E979 | A5 23 | LDA $23 | Load .A with the speed flag from DRVTRK+1 ($23). If the flag is not $00, no slow down is required so branch to ISR03. | |
E97B | D0 03 | BNE $E980 | JSR to SLOWD ($FEF3) to slow down the data transmission. | |
E97D | 20 F3 FE | JSR $FEF3 | ||
ISR03 | E980 | 20 FB FE | JSR $FEFB | JSR to CLKDAT ($FEFB) to pull the clock low and release the data. |
E983 | C6 98 | DEC $98 | Decrement the bit count in CONT ($98) . If the count is not $00, there are more bits to send from this byte so branch back to ISR01. | |
E985 | D0 D5 | BNE $E95C | ||
ISR04 | E987 | 20 59 EA | JSR $EA59 | JSR to DEBNC ($E9C0) to test if the data line has been set. |
E98A | 20 C0 E9 | JSR $E9C0 | AND the test byte (in .A) with $01. If the result equals $00, the line has not been set lo (no response) so branch back to ISR0.4 to wait for lo response. | |
E98D | 29 01 | AND #$01 | ||
E98F | F0 F6 | BEQ $E987 | ||
E991 | 58 | CLI | Clear the interrupt flag (CLI) to allow interrupts in preparation for sending the next byte. | |
E992 | 20 AA D3 | JSR $D3AA | JSR to GET ($D3AA) to get the next- data byte to send. | |
E995 | 78 | SEI | Set the interrupt flag (SEI) to prevent any interrupts. | |
E996 | 4C 0F E9 | JMP $E90F | JMP to TALK1 to keep on talking. | |
Talk subroutines |
||||
FRMERX | E999 | 4C 4E EA | JMP $EA4E | JMP to FRMERR ($EA4E) to release all lines and go to idle mode. |
DATHI | E99C | AD 00 18 | LDA $1800 | Set data out line high. Load .A with the byte from port B, PB ($1800), AND it with $FD ( $FF-DATOUT) , and store the result back in PB ($1800) . |
E99F | 29 FD | AND #$FD | ||
E9A1 | 8D 00 18 | STA $1800 | ||
E9A4 | 60 | RTS | Terminate routine with an RTS. | |
Set data out line lo |
||||
DATLOW | E9A5 | AD 00 18 | LDA $1800 | Load .A with the byte from port B, PB ($1800), OR it with $02 (DATOUT). and store the result back in PB ($1800) . |
E9A8 | 09 02 | ORA #$02 | ||
E9AA | 8D 00 18 | STA $1800 | ||
E9AD | 60 | RTS | Terminate routine with an RTS. | |
Set clock line lo |
||||
CLKLOW | E9AE | AD 00 18 | LDA $1800 | Load .A with the byte from port B, PB ($1800), OR it with $08 (CLKOUT). and store the result back in PB ($1800) . |
E9B1 | 09 08 | ORA #$08 | ||
E9B3 | 8D 00 18 | STA $1800 | ||
E9B6 | 60 | RTS | Terminate routine with an RTS. | |
Set clock line hi |
||||
CLKHI | E9B7 | AD 00 18 | LDA $1800 | Load .A with the byte from port B, PB ($1800). AND it with $F7 ($FF-CLKOUT) , and store the result back in PB ($1800) . |
E9BA | 29 F7 | AND #$F7 | ||
E9BC | 8D 00 18 | STA $1800 | ||
E9BF | 60 | RTS | Terminate routine with an RTS. | |
Wait for response on bus |
||||
DEBNC | E9C0 | AD 00 18 | LDA $1800 | Load .A with the byte from port. B, PB ($1800). Compare the old port value (.A) with the current value of PB ($1800). If there is no change, branch to DEBNC. |
E9C3 | CD 00 18 | CMP $1800 | ||
E9C6 | D0 F8 | BNE $E9C0 | ||
E9C8 | 60 | RTS | Terminate routine with an RTS. | |
Serial bus listen routines |
||||
ACPTR | E9C9 | A9 08 | LDA #$08 | Store $08 in CONT ($98) to set up the bit counter. |
E9CB | 85 98 | STA $98 | ||
ACP00A | E9CD | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal . |
E9D0 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the clock line has been set. | |
E9D3 | 29 04 | AND #$04 | AND the test byte (in .A) with $04. If the result is not $00, the line has not been set hi (no response) so branch back to ACP00A to wait for hi response. | |
E9D5 | D0 F6 | BNE $E9CD | ||
E9D7 | 20 9C E9 | JSR $E99C | JSR to DATHI ($E99C) to make data line high. | |
E9DA | A9 01 | LDA #$01 | Store $01 in T1HC1 ($1805) to set up for a 255 microsecond delay, | |
E9DC | 8D 05 18 | STA $1805 | ||
ACP00 | E9DF | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal . |
E9E2 | AD 0D 18 | LDA $180D | Load .A with the interrupt flag register from IFR1 ($180D) and AND the test byte with $40. If the result is NOT $00, the time has run out so it MUST be an EOI. Since it is an EOI, branch to ACPOOB. | |
E9E5 | 29 40 | AND #$40 | ||
E9E7 | D0 09 | BNE $E9F2 | ||
E9E9 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the clock line has been set. | |
E9EC | 29 04 | AND #$04 | AND the test byte (in .A) with $04. If the result is $00, the clock line has not been set lo (no response) so branch back to ACP00 to wait for lo response, If the result is not $00, the line has been set lo so branch to ACP01 to go on. | |
E9EE | F0 EF | BEQ $E9DF | ||
E9F0 | D0 19 | BNE $EA0B | ||
ACPOOB | E9F2 | 20 A5 E9 | JSR $E9A5 | JSR to DATLOW ($E9A5) to set data line low as a response. |
E9F5 | A2 0A | LDX #$0A | Load .X with $0A, and loop to count .X down to $00 to delay for talker turn around time. | |
E9F7 | CA | DEX | ||
E9F8 | D0 FD | BNE $E9F7 | ||
E9FA | 20 9C E9 | JSR $E99C | JSR to DATHI ($E99C) to make data line high. | |
ACP02A | E9FD | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. |
EA00 | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the clock line has been set. | |
EA03 | 29 04 | AND #$04 | AND the test byte (in .A) with $04. If the result is $00, the clock line has not been set lo (no response) so branch back to ACP02A to wait for lo response. | |
EA05 | F0 F6 | BEQ $E9FD | ||
ACP01 | EA07 | A9 00 | LDA #$00 | Store $00 in EOIFLG ($F8) to indicate that an EOI has been received. |
EA09 | 85 F8 | STA $F8 | ||
ACP03 | EA0B | AD 00 18 | LDA $1800 | Load .A with the data byte from port B, PB ($1800), EOR it with $01 to find the complement of the data bit, shift the data bit into the carry flag (LSR). AND the result in .A with $02 to test if the clock line has been set high to indicate valid data. If the result is NOT $00, the clock line has not been set hi yet so branch back to ACP03 and try again. |
EA0E | 29 04 | AND #$04 | ||
EA10 | D0 F9 | BNE $EA0B | ||
EA12 | AD 00 18 | LDA $1800 | ||
EA15 | 49 01 | EOR #$01 | Three $EA (NOP) bytes to fill space left by speed-up to fix VC20 901229-02 ROM ' s . | |
EA17 | 4A | LSR | ||
EA18 | 66 85 | ROR $85 | We have valid data bit in the carry so do a rotate right (ROR) on DATA ($85) to store the bit into the data byte. | |
ACP03A | EA1A | 20 59 EA | JSR $EA59 | JSR to TSTATN ($EA59) to test for an ATN signal. |
EA1D | 20 C0 E9 | JSR $E9C0 | JSR to DEBNC ($E9C0) to test if the clock line has been set. | |
EA20 | 29 04 | AND #$04 | AND the test byte (in .A) with $04. If the result is $00, the clock line has not been set lo (no response) so branch back to ACP03A to wait for lo response. | |
EA22 | F0 F6 | BEQ $EA1A | ||
EA24 | C6 98 | DEC $98 | Decrement the bit counter in CONT ($98) . If the count is not $00, there are more bits to get so branch back to ACP03. | |
EA26 | D0 E3 | BNE $EA0B | ||
EA28 | 20 A5 E9 | JSR $E9A5 | JSR to DATLOW ($E9A5) to set data line low das a response. | |
EA2B | A5 85 | LDA $85 | Load .A with the data byte from DATA ($85). | |
EA2D | 60 | RTS | Terminate routine with an RTS. | |
Main listen routine |
||||
LISTEN | EA2E | 78 | SEI | Set interrupt mask (SEI) to prevent any interrupts . |
EA2F | 20 07 D1 | JSR $D107 | JSR to FNDWCH ($D107) to find an unused write channel. If none available, branch to LSN15. | |
EA32 | B0 05 | BCS $EA39 | ||
EA34 | B5 F2 | LDA $F2,X | Load .A with the write channel status from CHNRDY,X ($F2,X). | |
EA36 | 6A | ROR | Rotate the status byte right (ROR). If the carry bit is set, the write channel is inactive so branch to LSN30. | |
EA37 | B0 0B | BCS $EA44 | ||
LSN15 | EA39 | A5 84 | LDA $84 | Test if this is an OPEN command by: loading .A with the original secondary address from ORGSA ($84)~ and AND'ing it with $F0. If the result is $F0, it is an OPEN command so branch to LSN30. |
EA3B | 29 F0 | AND #$F0 | ||
EA3D | C9 F0 | CMP #$F0 | ||
EA3F | F0 03 | BEQ $EA44 | ||
EA41 | 4C 4E EA | JMP $EA4E | Not an active channel so JMP to ILERR ($EA4E) to abort. | |
LSN30 | EA44 | 20 C9 E9 | JSR $E9C9 | JSR to ACPTR ($E9C9) to get a data byte. |
EA47 | 58 | CLI | Clear interrupt mask (CLI) to allow interrupts. | |
EA48 | 20 B7 CF | JSR $CFB7 | JSR to PUT ($CFB7) to put the data byte into its proper place (DATA, EOI. SA) . | |
EA4B | 4C 2E EA | JMP $EA2E | JMP to LISTEN ($EA2E) to keep on listening. | |
Release all bus lines and go idle |
||||
FRMERR | EA4E | A9 00 | LDA #$00 | Store $00 into port B, PB ($1800) and JMP to IDLE ($EBE7) . |
EA50 | 8D 00 18 | STA $1800 | ||
EA53 | 4C E7 EB | JMP $EBE7 | ||
Listen subroutines |
||||
ATNLOW | EA56 | 4C 5B E8 | JMP $E85B | JMP to ATNSRV ($E85B) to service ATN request. |
Test if in ATN mode |
||||
TSTATN | EA59 | A5 7D | LDA $7D | Load .A with the attention mode flag from ATNMOD ($7D). If $00, we are not in attention mode so branch to TSTA50. |
EA5B | F0 06 | BEQ $EA63 | ||
EA5D | AD 00 18 | LDA $1800 | We are in attention mode. Load .A with the byte from port B, PB ($1800). If bit 7 of this byte is clear, the ATN signal is gone so branch to TATN20 to do what we were told. | |
EA60 | 10 09 | BPL $EA6B | ||
TSTRTN | EA62 | 60 | RTS | The ATN signal hasn't gone away yet so exit with an RTS. |
TSTA50 | EA63 | AD 00 18 | LDA $1800 | We are not in attention mode now. Load .A with the byte from port B, PB ($1800) If bit 7 of this byte is clear, there is no ATN signal present so branch to TSTRTN to exit. If bit 7 of this byte is set, there is an ATN signal present so JMP to ATNSRV ($E85B) to service the ATN request. |
EA66 | 10 FA | BPL $EA62 | ||
EA68 | 4C 5B E8 | JMP $E85B | ||
TATN20 | EA6B | 4C D7 E8 | JMP $E8D7 | JMP to ATNS20 ($E8D7) to carry out the attention command . |
Flash led to signal error |
||||
No-error status |
||||
PEZRO | EA6E | A2 00 | LDX #$00 | Load .X with $00. |
EA70 | 2C | .BYTE $2C skips next two bytes. | ||
Error status |
||||
PERR | EA71 | A6 6F | LDX $6F | Load .X with the error number from TEMP ($6F) . |
EA73 | 9A | TXS | Transfer the error number from .X into the stack pointer to use the stack as a storage register. | |
PE20 | EA74 | BA | TSX | Transfer the value of the stack pointer (the error number) into .X |
PE30 | EA75 | A9 08 | LDA #$08 | Load .A with $08 (the LED mask). OR it with the data port controlling the LED's LEDPRT ($1C00). and JMP to PEA7A ($FEEA) to turn on LED. NOTE: this is a patch to be sure the data direction register for the LED line is set to output. |
EA77 | 0D 00 1C | ORA $1C00 | ||
EA7A | 4C EA FE | JMP $FEEA | ||
REA7D | EA7D | 98 | TYA | Transfer the byte in .Y to .A |
PD10 | EA7E | 18 | CLC | Clear the carry flag. |
PD20 | EA7F | 69 01 | ADC #$01 | Add $01 to the contents of .A. If the result is not $00, branch to PD20. |
EA81 | D0 FC | BNE $EA7F | ||
EA83 | 88 | DEY | Decrement .Y (the hi byte of the timer) . If value of .Y is not $00, branch to PD10. | |
EA84 | D0 F8 | BNE $EA7E | ||
Turn off LED(s) |
||||
EA86 | AD 00 1C | LDA $1C00 | Load .A with the byte from the data port controlling the LED, LEDPRT ($1C00). AND the byte with $F7 ($FF - LED mask) and store the result back into LEDPRT ($1C00) to turn OFF the LED. | |
EA89 | 29 F7 | AND #$F7 | ||
EA8B | 8D 00 1C | STA $1C00 | ||
PE40 | EA8E | 98 | TYA | Transfer the byte in .Y to .A |
PD11 | EA8F | 18 | CLC | Clear the carry flag. |
PD21 | EA90 | 69 01 | ADC #$01 | Add $01 to the contents of .A. 'if the result is not $00, branch to PD21. |
EA92 | D0 FC | BNE $EA90 | ||
EA94 | 88 | DEY | Decrement .Y (the hi byte of the timer) . If value of .Y is not $00, branch to PD11. | |
EA95 | D0 F8 | BNE $EA8F | ||
EA97 | CA | DEX | Decrement the count in .X. If the result is greater than or equal to $00, branch to PE30 to flash again. | |
EA98 | 10 DB | BPL $EA75 | ||
EA9A | E0 FC | CPX #$FC | Compare .X to $FC to see if we have waited long enough between groups of flashes. If .X <> $FC branch to PE40 to wait some more. If .X = $FC, branch to PE20 to repeat the sequence. | |
EA9C | D0 F0 | BNE $EA8E | ||
EA9E | F0 D4 | BEQ $EA74 | ||
Initialization of disk |
||||
DSKINT | EAA0 | 78 | SEI | Set the interrupt flag (SEI) to prevent interrupts . |
EAA1 | D8 | CLD | Clear the decimal mode flag (CLD) . | |
EAA2 | A2 FF | LDX #$FF | Store $FF into the data direction register DDRA1 ($1803). | |
EAA4 | 8E 03 18 | STX $1803 | ||
EAA7 | E8 | INX | Load .X and .Y with $00. | |
EAA8 | A0 00 | LDY #$00 | ||
EAAA | A2 00 | LDX #$00 | ||
PV10 | EAAC | 8A | TXA | Fill zero page with ascend ing pattern Transfer the byte from .X into .A. |
EAAD | 95 00 | STA $00,X | Store the byte from .A into $00, X. | |
EAAF | E8 | INX | Increment .X. If .X is not-$00, branch back to PV10. Check zero page bits. | |
EAB0 | D0 FA | BNE $EAAC | ||
PV20 | EAB2 | 8A | TXA | Transfer the byte from .X into .A. |
EAB3 | D5 00 | CMP $00,X | Compare the byte in .A with $00, X. If no match, branch to PEZRO ($EA6E) . | |
EAB5 | D0 B7 | BNE $EA6E | ||
PV30 | EAB7 | F6 00 | INC $00,X | Increment the contents of $00, X by 1. |
EAB9 | C8 | INY | Increment .Y. If .Y is not $00, branch back to PV3 0. | |
EABA | D0 FB | BNE $EAB7 | ||
EABC | D5 00 | CMP $00,X | Check if $00, X equals byte in .A. If no match, something is wrong so branch to PEZRO ($EA6E) . | |
EABE | D0 AE | BNE $EA6E | ||
EAC0 | 94 00 | STY $00,X | Store the $00 byte from .Y into $00, X. | |
EAC2 | B5 00 | LDA $00,X | Check if $00, X equals $00. If it does not, something is wrong so branch to PEZRO ($EA6E) . | |
EAC4 | D0 A8 | BNE $EA6E | ||
EAC6 | E8 | INX | Increment the counter in .X. If the result is not $00, we have more of zero page to check so branch back to PV20. | |
EAC7 | D0 E9 | BNE $EAB2 | ||
Test the two 64K bit ROM's |
||||
RM10 | EAC9 | E6 6F | INC $6F | Increment TEMP ($6F) to set the next error number ($01=$E/F; $02=$C/D ROM). |
EACB | 86 76 | STX $76 | Store .X value (page number) into IP+1 ($76) as the hi byte of the pointer. | |
EACD | A9 00 | LDA #$00 | ||
EACF | 85 75 | STA $75 | Set lo byte of pointer, IP ($75) to $00. | |
EAD1 | A8 | TAY | Set .Y to $00 and .X to $20 (32 pages) . | |
EAD2 | A2 20 | LDX #$20 | ||
EAD4 | 18 | CLC | Clear the carry flag. | |
RT10 | EAD5 | C6 76 | DEC $76 | Decrement the hi byte of the pointer in IP+1 ($76) and we'll do it backwards. |
RT20 | EAD7 | 71 75 | ADC ($75),Y | Add the ROM value from (IP),Y to the contents of .A, increment the Y pointer, and if .Y is not $00, branch back to RT20 to do another byte from this page. |
EAD9 | C8 | INY | ||
EADA | D0 FB | BNE $EAD7 | ||
EADC | CA | DEX | Decrement .X (page count). If the page count is not zero, branch to RT10 to do the next page of the ROM. | |
EADD | D0 F6 | BNE $EAD5 | ||
EADF | 69 00 | ADC #$00 | Add $00 to .A to add in the last carry. | |
EAE1 | AA | TAX | Transfer the checksum from .A to .X. | |
EAE2 | C5 76 | CMP $76 | Compare the checksum in .A with the hi byte of the count in IP+1 ($76). If the bytes do not match, branch to PERR2 ($EB1F). $E/F ROM: checksum = $E0 $C/D ROM: checksum = $C0 | |
EAE4 | D0 39 | BNE $EB1F | ||
EAE6 | E0 C0 | CPX #$C0 | Compare checksum in .X with $C0 to check if we are done. If not, branch to RM10. | |
EAE8 | D0 DF | BNE $EAC9 | ||
Test the disk RAM |
||||
CR20 | EAEA | A9 01 | LDA #$01 | Load .A with $01 (start of first block) . |
CR30 | EAEC | 85 76 | STA $76 | Save contents of .A (page number) into IP+1 ($76) as hi byte of pointer. |
EAEE | E6 6F | INC $6F | Increment TEMP ($6F) to bump the error number ($03=RAM problem) | |
RAMTST | EAF0 | A2 07 | LDX #$07 | Load .X with $07 (number of RAM pages) . |
RA10 | EAF2 | 98 | TYA | Transfer .Y value to .A and clear carry. |
EAF3 | 18 | CLC | ||
EAF4 | 65 76 | ADC $76 | Add the hi byte of the pointer, IP+1 ($76) to the accumulator and store the result in (IP,Y) . | |
EAF6 | 91 75 | STA ($75),Y | ||
EAF8 | C8 | INY | Increment .Y and if .Y is not. $00, branch to RA10 to fill RAM page. | |
EAF9 | D0 F7 | BNE $EAF2 | ||
EAFB | E6 76 | INC $76 | Increment the hi byte of the pointer in IP+1 ($76) and decrement the page count- in .X. If .X is not $00, we have more pages to do so branch back to RA10. | |
EAFD | CA | DEX | ||
EAFE | D0 F2 | BNE $EAF2 | ||
EB00 | A2 07 | LDX #$07 | Load .X with $07 (number of RAM pages) . | |
RA30 | EB02 | C6 76 | DEC $76 | Decrement the hi byte of the pointer in IP+1 ($76). We'll check backwards. |
RA40 | EB04 | 88 | DEY | Decrement .Y, transfer the .Y value into .A and clear the carry. |
EB05 | 98 | TYA | ||
EB06 | 18 | CLC | ||
EB07 | 65 76 | ADC $76 | Add the hi byte of the pointer, IP+1 ($76) to the accumulator and compare the result with (IP,Y). If they don't match, branch to PERR2 to report the error. | |
EB09 | D1 75 | CMP ($75),Y | ||
EB0B | D0 12 | BNE $EB1F | ||
EB0D | 49 FF | EOR #$FF | EOR the contents of .A with $FF to flip the bits and store the result into the RAM at (IP) ,Y. | |
EB0F | 91 75 | STA ($75),Y | ||
EB11 | 51 75 | EOR ($75),Y | EOR the contents of .A with (IP),Y and store the result (should be $00) back into (IP),Y. If the result is not $00, branch to PERR2 to report the error. | |
EB13 | 91 75 | STA ($75),Y | ||
EB15 | D0 08 | BNE $EB1F | ||
EB17 | 98 | TYA | Transfer the contents of .Y into .A. If .Y is not $00, we have more to do on this page so branch back to RA40. | |
EB18 | D0 EA | BNE $EB04 | ||
EB1A | CA | DEX | Decrement the page count in .X. If there are more pages to do, branch to RA30. | |
EB1B | D0 E5 | BNE $EB02 | ||
EB1D | F0 03 | BEQ $EB22 | Branch to DIAGOK. | |
PERR2 | EB1F | 4C 71 EA | JMP $EA71 | JMP to PERR ($EA71) to report error. |
DIAGOK | EB22 | A2 45 | LDX #$45 | Load .X with $45 and transfer this value to the stack pointer to reset the stack. |
EB24 | 9A | TXS | ||
EB25 | AD 00 1C | LDA $1C00 | Load .A with the byte from the LED control port, LEDPRT ($1C00), AND it with $F7 ($FF-LED mask) and store the result back in LEDPRT to turn off LED. | |
EB28 | 29 F7 | AND #$F7 | ||
EB2A | 8D 00 1C | STA $1C00 | ||
EB2D | A9 01 | LDA #$01 | Store $01 in PCR1 ($180C) to cause interrupt on the negative edge of ATN. | |
EB2F | 8D 0C 18 | STA $180C | ||
EB32 | A9 82 | LDA #$82 | Store $82 (10000010) in IFR1 ($180D) and IER1 ($180E) . | |
EB34 | 8D 0D 18 | STA $180D | ||
EB37 | 8D 0E 18 | STA $180E | ||
Compute device # from bits 5/6 of port B |
||||
EB3A | AD 00 18 | LDA $1800 | Load .A with the data byte from Port B, PB ($1800). AND the byte with $6 (%01100000). Do one ASL and three ROL ' s to convert from bits 6/5 to bits 1/0. NOTE: 0XX00000 becomes 000000XX | |
EB3D | 29 60 | AND #$60 | ||
EB3F | 0A | ASL | ||
EB40 | 2A | ROL | ||
EB41 | 2A | ROL | ||
EB42 | 2A | ROL | ||
EB43 | 09 48 | ORA #$48 | OR .A with $48 (the talk address) and store the result in TLKADR ($78) . EOR .A with $60 (the listen address) and store the result in LSNADR ($77) . | |
EB45 | 85 78 | STA $78 | ||
EB47 | 49 60 | EOR #$60 | ||
EB49 | 85 77 | STA $77 | ||
Initialize buffer pointer table |
||||
INTTAB | EB4B | A2 00 | LDX #$00 | Zero .X and .Y |
EB4D | A0 00 | LDY #$00 | ||
INTT1 | EB4F | A9 00 | LDA #$00 | Zero .A and store the $00 byte in .A in the buffer table at BUFTAB,X ($99, X). |
EB51 | 95 99 | STA $99,X | ||
EB53 | E8 | INX | Increment .X and load .A with the hi byte of the pointer to the buffer from BUFIND,Y ($FEE0) and store it into the buffer table at BUFTAB,X ($99, X). | |
EB54 | B9 E0 FE | LDA $FEE0,Y | ||
EB57 | 95 99 | STA $99,X | ||
EB59 | E8 | INX | Increment .X and .Y and compare the new value of .Y with $05 (the number of buffers). If there are more buffers to do, branch to INTT1. | |
EB5A | C8 | INY | ||
EB5B | C0 05 | CPY #$05 | ||
EB5D | D0 F0 | BNE $EB4F | ||
EB5F | A9 00 | LDA #$00 | Store the lo byte of the pointer to the command buffer ($00) into the buffer table at BUFTAB,X ($99, X). Increment .X. | |
EB61 | 95 99 | STA $99,X | ||
EB63 | E8 | INX | ||
EB64 | A9 02 | LDA #$02 | Store the hi byte of the pointer to the command buffer ($02) into the buffer table at BUFTAB,X ($99, X). Increment .X. | |
EB66 | 95 99 | STA $99,X | ||
EB68 | E8 | INX | ||
EB69 | A9 D5 | LDA #$D5 | Store the lo byte of the pointer to the error buffer ($D5) into the buffer table table at BUFTAB,X ($99, X). Increment .X. | |
EB6B | 95 99 | STA $99,X | ||
EB6D | E8 | INX | ||
EB6E | A9 02 | LDA #$02 | Store the hi byte of the pointer to the error buffer ($02) into the buffer table table at BUFTAB,X ($99, X). Increment .X. | |
EB70 | 95 99 | STA $99,X | ||
EB72 | A9 FF | LDA #$FF | Load .A with $FF (inactive SA) and .X with $12 (the maximum secondary address) | |
EB74 | A2 12 | LDX #$12 | ||
DSKIN1 | EB76 | 9D 2B 02 | STA $022B,X | Loop to set all LINTAB,X ($022B,X) values to $FF to indicate inactive. |
EB79 | CA | DEX | ||
EB7A | 10 FA | BPL $EB76 | ||
EB7C | A2 05 | LDX #$05 | Load .X with $05 (the maximum number of channels - 1) . | |
DSKIN2 | EB7E | 95 A7 | STA $A7,X | Loop to set all BUF0,X ($A7,X), BUF1,X ($AE,X) and SS,X (CD,X) values to $FF to indicate that these buffers are unused. |
EB80 | 95 AE | STA $AE,X | ||
EB82 | 95 CD | STA $CD,X | ||
EB84 | CA | DEX | ||
EB85 | 10 F7 | BPL $EB7E | ||
EB87 | A9 05 | LDA #$05 | Store $05 (the buffer count) into BUFO+CMDCHN ($AB) | |
EB89 | 85 AB | STA $AB | ||
EB8B | A9 06 | LDA #$06 | Store $05 (the buffer count + 1) into BUF0+ERRCHN ($AC) | |
EB8D | 85 AC | STA $AC | ||
EB8F | A9 FF | LDA #$FF | Store $FF into BUF0+BLINDX ($AD) | |
EB91 | 85 AD | STA $AD | ||
EB93 | 85 B4 | STA $B4 | Store $FF into BUF1+BLINDX ($B4) | |
EB95 | A9 05 | LDA #$05 | Store $05 (the error channel #) into LINTAB+ERRSA ($023B) . | |
EB97 | 8D 3B 02 | STA $023B | ||
EB9A | A9 84 | LDA #$84 | Store $84 ($80 + the command channel #) into LINTAB+CMDSA ($023A) . | |
EB9C | 8D 3A 02 | STA $023A | ||
EB9F | A9 0F | LDA #$0F | Store $0F (LINDX to 5 free) into LINUSE ($0256) . | |
EBA1 | 8D 56 02 | STA $0256 | ||
EBA4 | A9 01 | LDA #$01 | Store $01 (ready to listen) into CHNRDY+CMDCHN ($F6) . | |
EBA6 | 85 F6 | STA $F6 | ||
EBA8 | A9 88 | LDA #$88 | Store $01 (ready to talk) into CHNRDY+ERRCHN ($F7) . | |
EBAA | 85 F7 | STA $F7 | ||
EBAC | A9 E0 | LDA #$E0 | Store $E0 into BUFUSE ($024F) and $FF into BUFUSE+1 ($0250) . | |
EBAE | 8D 4F 02 | STA $024F | ||
EBB1 | A9 FF | LDA #$FF | ||
EBB3 | 8D 50 02 | STA $0250 | ||
EBB6 | A9 01 | LDA #$01 | Store $01 into WPSW ($1C) and WPSW+1 ($1D) to set up the write protect status | |
EBB8 | 85 1C | STA $1C | ||
EBBA | 85 1D | STA $1D | ||
EBBC | 20 63 CB | JSR $CB63 | JSR to USRINT ($CB63) to initialize the user jump table. | |
EBBF | 20 FA CE | JSR $CEFA | JSR to LRUINT ($CEFA) to initialize the least recently used table. | |
EBC2 | 20 59 F2 | JSR $F259 | JSR to CNTINT ($F259) to initialize the disk controller. | |
EBC5 | A9 22 | LDA #$22 | Set up the indirect NMI vector at VNMI ($65/6) to point to the diagnostic routine, DIAGOK ($EB22). | |
EBC7 | 85 65 | STA $65 | ||
EBC9 | A9 EB | LDA #$EB | ||
EBCB | 85 66 | STA $66 | ||
EBCD | A9 0A | LDA #$0A | Store $0A into SECINC ($69) as the normal next sector increment. | |
EBCF | 85 69 | STA $69 | ||
EBD1 | A9 05 | LDA #$05 | Store $05 into REVCNT ($6A) as the normal recovery counter. | |
EBD3 | 85 6A | STA $6A | ||
SETERR | EBD5 | A9 73 | LDA #$73 | Load .A with $73 and JSR to ERRTSO ($E6C1) to set up power-on error message 73 CBM DOS V2.6 1541 |
EBD7 | 20 C1 E6 | JSR $E6C1 | ||
EBDA | A9 1A | LDA #$1A | Load .A with $1A (%00011010) and store it in the data direction register DDRB1 ($1802). ATNA,CLKOUT,DATOUT are outputs. | |
EBDC | 8D 02 18 | STA $1802 | ||
EBDF | A9 00 | LDA #$00 | Store $00 in data port B, PB ($1800) to set DATA, CLOCK, & ATNA lines high. | |
EBE1 | 8D 00 18 | STA $1800 | ||
EBE4 | 20 80 E7 | JSR $E780 | JSR to BOOT ($E780) to see if we need to boot a systems routine. | |
Idle loop. Wait for something to do. |
||||
IDLE | EBE7 | 58 | CLI | Clear interrupt mask (CLI) to allow interrupts. |
Release all the bus lines |
||||
EBE8 | AD 00 18 | LDA $1800 | Load .A with the byte from port B, PB ($1800), AND it with $E5 to set CLOCK, DATA, and ATNA lines high, and store the result back in PB ($1800) . | |
EBEB | 29 E5 | AND #$E5 | ||
EBED | 8D 00 18 | STA $1800 | ||
EBF0 | AD 55 02 | LDA $0255 | Check the value of CMDWAT ($0255) to see if there is a command waiting. If it is $00, there is none waiting so branch to IDL1. | |
EBF3 | F0 0A | BEQ $EBFF | ||
EBF5 | A9 00 | LDA #$00 | Store $00 in CMDWAT ($0255) to clear the command waiting flag. | |
EBF7 | 8D 55 02 | STA $0255 | ||
EBFA | 85 67 | STA $67 | Store $00 in NMIFLG ($67) to clear the debounce. | |
EBFC | 20 46 C1 | JSR $C146 | JSR to PARSXQ ($C146) to parse and then execute the command. | |
IDL1 | EBFF | 58 | CLI | Clear interrupt mask (CLI) to allow interrupts. |
EC00 | A5 7C | LDA $7C | Check the value of ATNPND ($0255) to see if there is an attention pending. If it- is $00, there is nothing pending (such as the drive running or an open file) so branch to IDL01. | |
EC02 | F0 03 | BEQ $EC07 | ||
EC04 | 4C 5B E8 | JMP $E85B | JMP to ATNSRV ($E85B) to service the attention request. | |
IDL01 | EC07 | 58 | CLI | Clear interrupt mask (CLI) to allow interrupts . |
EC08 | A9 0E | LDA #$0E | Store $0E (#14). the maximum secondary address for files in TEMP+3 ($72) . | |
EC0A | 85 72 | STA $72 | ||
EC0C | A9 00 | LDA #$00 | Zero TEMP ($6F) and TEMP+1 ($70). | |
EC0E | 85 6F | STA $6F | ||
EC10 | 85 70 | STA $70 | ||
IDL02 | EC12 | A6 72 | LDX $72 | Load .X with the secondary address counter from TEMP+3 ($72) . |
EC14 | BD 2B 02 | LDA $022B,X | Load .A with the channel number for this secondary address from LINTAB,X ($022B,X) If it is $FF, there is no active file for this SA so branch to IDL3. | |
EC17 | C9 FF | CMP #$FF | ||
EC19 | F0 10 | BEQ $EC2B | ||
EC1B | 29 3F | AND #$3F | We've found an active file so AND the channel number with $3F and store the result as the current channel number in LINDX ($82) . | |
EC1D | 85 82 | STA $82 | ||
EC1F | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
EC22 | AA | TAX | Transfer the buffer number from .A to .X | |
EC23 | BD 5B 02 | LDA $025B,X | Determine which drive is to be used by loading the old job number from LSTJOB,X ($025B,X), AND'ing it with $01, and transferring the result into .X. | |
EC26 | 29 01 | AND #$01 | ||
EC28 | AA | TAX | ||
EC29 | F6 6F | INC $6F,X | Increment the count of the number of active files on drive X in TEMP,X ($6F,X) | |
IDL3 | EC2B | C6 72 | DEC $72 | Decrement the SA count in TEMP + 3 ($72) . If there are more secondary addresses left to check, branch back to IDL2. |
EC2D | 10 E3 | BPL $EC12 | ||
EC2F | A0 04 | LDY #$04 | Load .Y with $04 (the number of buffers less 1) . | |
IDL4 | EC31 | B9 00 00 | LDA $0000,Y | Load .A with the current job code for this buffer from the job queue, JOBS,Y ($00, Y). If bit 7 is not set, no job is in progress so branch to IDL5. |
EC34 | 10 05 | BPL $EC3B | ||
EC36 | 29 01 | AND #$01 | There is a job in progress so AND the job code in .A with $01 to mask off the non-drive bits and transfer the result- to .X. | |
EC38 | AA | TAX | ||
EC39 | F6 6F | INC $6F,X | Increment the count of the number of active files on drive X in TEMP,X ($6F ,X) | |
IDL5 | EC3B | 88 | DEY | Decrement the buffer counter in .Y. If there are more buffers to check, branch to IDL4. |
EC3C | 10 F3 | BPL $EC31 | ||
EC3E | 78 | SEI | Set the interrupt mask (SEI) to prevent interrupts while reading LEDPRT ($1C00) . | |
EC3F | AD 00 1C | LDA $1C00 | Load .A with the data byte from the port controlling the LED, AND the byte with $F7 ($FF - LED mask). and save the result onto the stack. | |
EC42 | 29 F7 | AND #$F7 | ||
EC44 | 48 | PHA | ||
EC45 | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F) and save it in R0($86) | |
EC47 | 85 86 | STA $86 | ||
EC49 | A9 00 | LDA #$00 | Zero DRVNUM ($7F) . | |
EC4B | 85 7F | STA $7F | ||
EC4D | A5 6F | LDA $6F | Test the active file count for drive in TEMP ($6F). If $00, branch to IDL7. | |
EC4F | F0 0B | BEQ $EC5C | ||
EC51 | A5 1C | LDA $1C | Load the write protect switch byte from WPSW ($1C). If it is $00 branch to IDL6. | |
EC53 | F0 03 | BEQ $EC58 | ||
EC55 | 20 13 D3 | JSR $D313 | JSR to CLDCHN ($D313) to close all files | |
IDL6 | EC58 | 68 | PLA | Pull the LED data byte off the stack, OR it with $08 (LED mask) to turn on the LED since drive is active, and save the byte back onto the stack. |
EC59 | 09 08 | ORA #$08 | ||
EC5B | 48 | PHA | ||
IDL7 | EC5C | E6 7F | INC $7F | Increment the DRVNUM ($7F). (to $01) |
EC5E | A5 70 | LDA $70 | Test the active file count for drive 1 in TEMP+1 ($70). If $00, branch to IDL9. | |
EC60 | F0 0B | BEQ $EC6D | ||
EC62 | A5 1D | LDA $1D | Load the write protect switch byte from WPSW ($1C). If it is $00 branch to IDL8. | |
EC64 | F0 03 | BEQ $EC69 | ||
EC66 | 20 13 D3 | JSR $D313 | JSR to CLDCHN ($D313) to close all files | |
IDL8 | EC69 | 68 | PLA | Pull the LED data byte off the stack, OR it. with $00 (LED mask) to turn on the LED since drive 1 is active. and save the byte back onto the stack. |
EC6A | 09 00 | ORA #$00 | ||
EC6C | 48 | PHA | ||
IDL9 | EC6D | A5 86 | LDA $86 | Copy the original drive number from R0 ($86) back into DRVNUM ($7F) . |
EC6F | 85 7F | STA $7F | ||
EC71 | 68 | PLA | Pull the LED data byte off the stack. | |
EC72 | AE 6C 02 | LDX $026C | Load .X with the error status from ERWORD ($026C). If it is $00, the LED is not flashing so branch to IDL12. | |
EC75 | F0 21 | BEQ $EC98 | ||
Error light is flashing |
||||
EC77 | AD 00 1C | LDA $1C00 | Load .A with the LED data byte from LEDPRT ($1C00) | |
EC7A | E0 80 | CPX #$80 | Compare the error status in .X with $80. If it is not $80, this is not the first time we have seen this error so branch to IDL 10. | |
EC7C | D0 03 | BNE $EC81 | ||
EC7E | 4C 8B EC | JMP $EC8B | We have just encountered a new error status so JMP to IDL11. | |
IDL10 | EC81 | AE 05 18 | LDX $1805 | Load .X with the value of TIMER1 ($1805) If bit 7 is set, we are still timing so branch to IDL12. |
EC84 | 30 12 | BMI $EC98 | ||
EC86 | A2 A0 | LDX #$A0 | Store $A0 into TIMER1 ($1805) to set the timer to a new 8 millisecond cycle. | |
EC88 | 8E 05 18 | STX $1805 | ||
IDL11 | EC8B | CE 6C 02 | DEC $026C | Decrement the count of 8 millisecond cycles in ERWORD ($026C). If the count is not $00 yet, branch to IDL12 |
EC8E | D0 08 | BNE $EC98 | ||
EC90 | 4D 6D 02 | EOR $026D | Time is up. EOR the LED status in .A with the LED mask in ERLED ($026D) to toggle the LED. | |
EC93 | A2 10 | LDX #$10 | Store $10 in ERWORD ($026C) to start a new timing cycle. | |
EC95 | 8E 6C 02 | STX $026C | ||
IDL12 | EC98 | 8D 00 1C | STA $1C00 | Store the current LED status (in .A) into the LED port, LEDPRT ($1C00). |
EC9B | 4C FF EB | JMP $EBFF | JMP to IDL1 ($EBFF) the top of the loop. | |
Start loading the directory |
||||
STDIR | EC9E | A9 00 | LDA #$00 | Set current secondary address, SA ($83) to $00. |
ECA0 | 85 83 | STA $83 | ||
ECA2 | A9 01 | LDA #$01 | Load .A with $01 and JSR to GETRCH ($D1E2) to allocate a channel and one buffer. | |
ECA4 | 20 E2 D1 | JSR $D1E2 | ||
ECA7 | A9 00 | LDA #$00 | Zero .A and JSR to SETPNT ($D4C8) to set the buffer pointer to the start of the buffer. | |
ECA9 | 20 C8 D4 | JSR $D4C8 | ||
ECAC | A6 82 | LDX $82 | Load .X with the channel number from LINDX ($82) . | |
ECAE | A9 00 | LDA #$00 | Store $00 as the last character for this channel in LSTCHR,X ($0244). | |
ECB0 | 9D 44 02 | STA $0244,X | ||
ECB3 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
ECB6 | AA | TAX | Transfer the buffer number into .X | |
ECB7 | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F) and store this number as the last job number for this buffer in LSTJOB,X ($025B) . | |
ECB9 | 9D 5B 02 | STA $025B,X | ||
ECBC | A9 01 | LDA #$01 | Load .A with $01 and JSR to PUTBYT ($CFF1) to put the lo byte of the load address ($0401) into the buffer. | |
ECBE | 20 F1 CF | JSR $CFF1 | ||
ECC1 | A9 04 | LDA #$04 | Load .A with $04 and JSR to PUTBYT ($CFF1) to put the hi byte of the load address ($0401) into the buffer. | |
ECC3 | 20 F1 CF | JSR $CFF1 | ||
ECC6 | A9 01 | LDA #$01 | Load .A with $01 and JSR to PUTBYT ($CFF1) twice to put a phony program line link ($0101) into the buffer. | |
ECC8 | 20 F1 CF | JSR $CFF1 | ||
ECCB | 20 F1 CF | JSR $CFF1 | ||
ECCE | AD 72 02 | LDA $0272 | Load .A with the drive number for the directory from NBTEMP ($0272) and JSR to PUTBYT ($CFF1) to put this to the buffer as the lo byte of the first line number. | |
ECD1 | 20 F1 CF | JSR $CFF1 | ||
ECD4 | A9 00 | LDA #$00 | Load .A with $00 and JSR to PUTBYT ($CFF1) to store this as the hi byte of the line number. | |
ECD6 | 20 F1 CF | JSR $CFF1 | ||
ECD9 | 20 59 ED | JSR $ED59 | JSR to MOVBUF ($ED59) to move the disk name into the buffer. | |
ECDC | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
ECDF | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer it. into .X. | |
ECE0 | AA | TAX | ||
ECE1 | D6 99 | DEC $99,X | Decrement the lo byte of the pointer in BUFTAB,X ($$99, X) twice. | |
ECE3 | D6 99 | DEC $99,X | ||
ECE5 | A9 00 | LDA #$00 | Load .A with $00 and JSR to PUTBYT ($CFF1) to store this as the end of program line null byte. | |
ECE7 | 20 F1 CF | JSR $CFF1 | ||
DIR1 | ECEA | A9 01 | LDA #$01 | Load .A with $01 and JSR to PUTBYT ($CFF1) twice to put a phony program line link ($0101) into the buffer. |
ECEC | 20 F1 CF | JSR $CFF1 | ||
ECEF | 20 F1 CF | JSR $CFF1 | ||
ECF2 | 20 CE C6 | JSR $C6CE | JSR to GETNAM ($C6CE) to get the buffer number and file name. If the carry flag is clear on return, this is the last- entry so branch to DIR3. | |
ECF5 | 90 2C | BCC $ED23 | ||
ECF7 | AD 72 02 | LDA $0272 | Load .A with the lo byte of the block count from NBTEMP ($0272) and JSR to PUTBYT ($CFF1) to put this to the buffer as the lo byte of the line number. | |
ECFA | 20 F1 CF | JSR $CFF1 | ||
ECFD | AD 73 02 | LDA $0273 | Load .A with the hi byte of the block count from NBTEMP+1 ($0273) and JSR to PUTBYT ($CFF1) to put this to the buffer as the hi byte of the line number. | |
ED00 | 20 F1 CF | JSR $CFF1 | ||
ED03 | 20 59 ED | JSR $ED59 | JSR to MOVBUF ($ED59) to move the file name and file type into the buffer. | |
ED06 | A9 00 | LDA #$00 | Load .A with $00 and JSR to PUTBYT ($CFF1) to store this as the end of program line null byte. | |
ED08 | 20 F1 CF | JSR $CFF1 | ||
ED0B | D0 DD | BNE $ECEA | If the Z flag is not set on return, the buffer is not full so branch to DIR1 to do the next file entry. | |
DIR10 | ED0D | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . |
ED10 | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer it into .X. | |
ED11 | AA | TAX | ||
ED12 | A9 00 | LDA #$00 | Store $00 as the lo byte of the pointer in BUFTAB,X ($$99, X) . | |
ED14 | 95 99 | STA $99,X | ||
ED16 | A9 88 | LDA #$88 | Load .A with $88 (ready-to-talk) . | |
ED18 | A4 82 | LDY $82 | Load .Y with the channel number from LINDX ($82) . | |
ED1A | 8D 54 02 | STA $0254 | Store $88 (in .A) into the directory list flag DIRLST ($0254) to indicate that the directory list is full. | |
ED1D | 99 F2 00 | STA $00F2,Y | Store $88 (in .A) as the channel status in CHNRDY,Y ($00F2,Y). | |
ED20 | A5 85 | LDA $85 | Load .A with the byte from DATA ($85) . | |
ED22 | 60 | RTS | Terminate routine with an RTS. | |
End directory loading |
||||
DIR3 | ED23 | AD 72 02 | LDA $0272 | Load .A with the lo byte of the block count from NBTEMP ($0272) and JSR to PUTBYT ($CFF1) to put this to the buffer as the lo byte of the line number. |
ED26 | 20 F1 CF | JSR $CFF1 | ||
ED29 | AD 73 02 | LDA $0273 | Load .A with the hi byte of the block count from NBTEMP+1 ($0273) and JSR to PUTBYT ($CFF1) to put this to the buffer as the hi byte of the line number. | |
ED2C | 20 F1 CF | JSR $CFF1 | ||
ED2F | 20 59 ED | JSR $ED59 | JSR to MOVBUF ($ED59) to move the file name and file type into the buffer. | |
ED32 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
ED35 | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer it into .X. | |
ED36 | AA | TAX | ||
ED37 | D6 99 | DEC $99,X | Decrement the lo byte of the pointer in BUFTAB,X ($$99, X) twice. | |
ED39 | D6 99 | DEC $99,X | ||
ED3B | A9 00 | LDA #$00 | Load .A with $00 and JSR to PUTBYT ($CFF1) three times to store the three null bytes at the end of a program. | |
ED3D | 20 F1 CF | JSR $CFF1 | ||
ED40 | 20 F1 CF | JSR $CFF1 | ||
ED43 | 20 F1 CF | JSR $CFF1 | ||
ED46 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to get the active buffer number (returned in .A) . | |
ED49 | 0A | ASL | Multiply the buffer number by 2 (ASL) and transfer it into .Y. | |
ED4A | A8 | TAY | ||
ED4B | B9 99 00 | LDA $0099,Y | Load .A with the lo byte of the pointer into the buffer from BUFTAB,Y ($0099, Y). | |
ED4E | A6 82 | LDX $82 | Load .Y with the channel number from LINDX ($82) . | |
ED50 | 9D 44 02 | STA $0244,X | Store the lo byte of the pointer (in .A) into the lo byte of the pointer to the last non-zero character in the buffer LSTCHR,X ($0244, X). | |
ED53 | DE 44 02 | DEC $0244,X | Decrement the pointer in LSTCHR,X ($0244, X) by 1 so it does actually point to the last character in the buffer. | |
ED56 | 4C 0D ED | JMP $ED0D | JMP to DIR10 ($ED0D) to set the channel status and flags and exit. | |
MOVBUF | ED59 | A0 00 | LDY #$00 | Transfer file name to listing buffer Zero .Y |
MOVB1 | ED5B | B9 B1 02 | LDA $02B1,Y | Load .A with the character from NAMBUF,Y ($02B1,Y) and JSR to PUTBYT ($CFF1) to store it in the listing buffer. |
ED5E | 20 F1 CF | JSR $CFF1 | ||
ED61 | C8 | INY | Increment .Y. If .Y is not $1B (#27) yet, branch to MOVB1. | |
ED62 | C0 1B | CPY #$1B | ||
ED64 | D0 F5 | BNE $ED5B | ||
ED66 | 60 | RTS | Terminate routine with an RTS. | |
Get character for directory load |
||||
GETDIR | ED67 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to get a byte from the data buffer (loads next block if necessary) . |
ED6A | F0 01 | BEQ $ED6D | On return, if the Z flag is set, we are at the end-of-file so branch to GETD3. | |
ED6C | 60 | RTS | Terminate routine with an RTS. | |
GETD3 | ED6D | 85 85 | STA $85 | Store the byte (in .A) into DATA ($85). |
ED6F | A4 82 | LDY $82 | Load .Y with the channel number from LINDX ($82) . | |
ED71 | B9 44 02 | LDA $0244,Y | Load .A with the lo byte of the pointer into the directory buffer from LSTCHR,Y ($0244, Y) | |
ED74 | F0 08 | BEQ $ED7E | If the lo byte of the pointer is $00, we have exhasted the current buffer so branch to GD1. | |
ED76 | A9 80 | LDA #$80 | We must be at the end-of-file so load .A with $8 (EOI) and st ore it as the channel status in CHNRDY,Y ($00F2,Y). | |
ED78 | 99 F2 00 | STA $00F2,Y | ||
ED7B | A5 85 | LDA $85 | Load .A with the byte from DATA ($85). | |
ED7D | 60 | RTS | Terminate routine with an RTS. | |
GD1 | ED7E | 48 | PHA | Save the null byte in .A onto the stack, |
ED7F | 20 EA EC | JSR $ECEA | JSR to DIR1 ($ECEA) to create pseudo program listing in the listing buffer. | |
ED82 | 68 | PLA | Pull the null data byte off the stack. | |
ED83 | 60 | RTS | Terminate routine with an RTS. | |
Validate (collect) disk commandCreate a new BAM to match the sectors used by the current directory entries. |
||||
VERDIR | ED84 | 20 D1 C1 | JSR $C1D1 | JSR to SIMPRS ($C1D1) to parse the command string and extract the drive #. |
ED87 | 20 42 D0 | JSR $D042 | JSR to INITDR ($D042) to initialize the drive specified. | |
ED8A | A9 40 | LDA #$40 | Store $40 in WBAM ($02F9) to mark BAM as dirty (needs to be written out) . | |
ED8C | 8D F9 02 | STA $02F9 | ||
ED8F | 20 B7 EE | JSR $EEB7 | JSR to NEWMAP ($EEB7) to build a new blank BAM in RAM. | |
ED92 | A9 00 | LDA #$00 | Store $00 in DELIND ($0292) to force a search for a valid directory entry and JSR to SRCHST ($C5AC) to search the directory for the first valid entry. | |
ED94 | 8D 92 02 | STA $0292 | ||
ED97 | 20 AC C5 | JSR $C5AC | ||
ED9A | D0 3D | BNE $EDD9 | If an entry is found (Z flag not set) , branch to VD25 to process it. | |
No more entries so finish up. |
||||
VD10 | ED9C | A9 00 | LDA #$00 | Set SECTOR ($81) to $00. |
ED9E | 85 81 | STA $81 | ||
EDA0 | AD 85 FE | LDA $FE85 | Set TRACK ($80) with the value $12 (#18) from DIRTRK ($FE85) . | |
EDA3 | 85 80 | STA $80 | ||
EDA5 | 20 E5 ED | JSR $EDE5 | JSR to VMKBAM ($EDE5) to trace through the directory sectors and mark those in use in the BAM. | |
EDA8 | A9 00 | LDA #$00 | Store $00 in WBAM ($02F9) to mark BAM as clean (BAM in RAM matches BAM on disk) . | |
EDAA | 8D F9 02 | STA $02F9 | ||
EDAD | 20 FF EE | JSR $EEFF | JSR to SCRBAM ($EEFF) to write BAM out to disk. | |
EDB0 | 4C 94 C1 | JMP $C194 | Terminate command with a JMP to ENDCMD (SC194) . | |
Process directory entry for BAM |
||||
VD15 | EDB3 | C8 | INY | Increment .Y (points to entry in buffer) |
EDB4 | B1 94 | LDA ($94),Y | Load the track link for the entry from (DIRBUF) ,Y; ($94), Y and save it onto the stack. | |
EDB6 | 48 | PHA | ||
EDB7 | C8 | INY | Increment .Y (points to entry in buffer) | |
EDB8 | B1 94 | LDA ($94),Y | Load the sector link for the entry from (DIRBUF) ,Y; ($94) ,Y and save it onto the stack. | |
EDBA | 48 | PHA | ||
EDBB | A0 13 | LDY #$13 | Load .Y with $13 so it points to the side sector track link of the entry. | |
EDBD | B1 94 | LDA ($94),Y | Load the SS track link for the entry from (DIRBUF) ,Y; ($94) ,Y. If the SS track link is $00, this isn't a relative file so branch to VD17. | |
EDBF | F0 0A | BEQ $EDCB | ||
EDC1 | 85 80 | STA $80 | Store the SS track link in TRACK ($80) . | |
EDC3 | C8 | INY | Increment .Y (points to entry in buffer) | |
EDC4 | B1 94 | LDA ($94),Y | Load the SS sector link for the entry from (DIRBUF) ,Y; ($94) ,Y. Store the SS sector link in SECTOR ($81) . | |
EDC6 | 85 81 | STA $81 | ||
EDC8 | 20 E5 ED | JSR $EDE5 | JSR to VMKBAM ($EDE5) to trace through the SS file and mark the sectors used in the BAM. | |
VD17 | EDCB | 68 | PLA | Pull the main file's sector link off the stack and store it in SECTOR ($81) . |
EDCC | 85 81 | STA $81 | ||
EDCE | 68 | PLA | Pull the main file's track link off the stack and store it in TRACK ($80) . | |
EDCF | 85 80 | STA $80 | ||
EDD1 | 20 E5 ED | JSR $EDE5 | JSR to VMKBAM ($EDE5) to trace through the main file and mark the sectors used in the BAM. | |
VD20 | EDD4 | 20 04 C6 | JSR $C604 | JSR to SRRE ($C604) to search for the next valid directory entry. |
EDD7 | F0 C3 | BEQ $ED9C | If another entry is not found (Z flag is set) branch to VD10 to finish up. | |
Check if entry found is properly closed |
||||
VD25 | EDD9 | A0 00 | LDY #$00 | Zero .Y so it points to the first character in the entry, the file type. |
EDDB | B1 94 | LDA ($94),Y | Load .A with the file type byte from (DIRBUF) ,Y; ($99) ,Y. If bit 7 is set, the file has been properly closed so branch to VD15 to process it. | |
EDDD | 30 D4 | BMI $EDB3 | ||
EDDF | 20 B6 C8 | JSR $C8B6 | File was not properly closed so JSR to DELDIR ($C8B6) to delete it from the directory. | |
EDE2 | 4C D4 ED | JMP $EDD4 | JMP to VD20 ($EDD4) to find next entry. | |
Trace file by links and mark BAM |
||||
VMKBAM | EDE5 | 20 5F D5 | JSR $D55F | JSR to TSCHK ($D55F) to check that the TRACK and SECTOR values are legal. |
EDE8 | 20 90 EF | JSR $EF90 | JSR to WUSED ($EF90) to mark the sector pointed to by TRACK and SECTOR as IN USE in the BAM. | |
EDEB | 20 75 D4 | JSR $D475 | JSR to OPNIRD ($D475) to open the internal read channel and read in the first one or two file blocks. | |
MRK2 | EDEE | A9 00 | LDA #$00 | Load .A with $00 and JSR to SETPNT ($D4C8) to set the pointers to the first byte in the buffer (the track link) . |
EDF0 | 20 C8 D4 | JSR $D4C8 | ||
EDF3 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read the track link (in .A). Store it into TRACK ($80). | |
EDF6 | 85 80 | STA $80 | ||
EDF8 | 20 37 D1 | JSR $D137 | JSR to GETBYT ($D137) to read the sector link (in .A). Store it into SECTOR ($81) | |
EDFB | 85 81 | STA $81 | ||
EDFD | A5 80 | LDA $80 | Load .A with the track link from TRACK ($80). If it is not $00, branch to MRK1. | |
EDFF | D0 03 | BNE $EE04 | ||
EE01 | 4C 27 D2 | JMP $D227 | Track link is $00. This must be the last block in the file so JMP to FRECHN ($D227) to free the channel and return. | |
MRK1 | EE04 | 20 90 EF | JSR $EF90 | JSR to WUSED ($EF90) to mark the sector pointed to by TRACK and SECTOR as IN USE in the BAM. |
EE07 | 20 4D D4 | JSR $D44D | JSR to NXTBUF ($D44D) to read in the next block of the file. | |
EE0A | 4C EE ED | JMP $EDEE | JMP to MRK2 ($EDEE) to do next block. | |
New (format) disk commandA full, or long NEW marks off the tracks and sectors on a diskette, writes null data blocks in all sectors, and creates a new BAM and directory on track 18. A short NEW merely creates a new BAM and directory on track 18. |
||||
NEW | EE0D | 20 12 C3 | JSR $C312 | JSR to ONEDRV ($C312) to set up drive and table pointers. |
EE10 | A5 E2 | LDA $E2 | Load the number of the drive that was set up from FILDRV ($E2). If bit 7 is not set, a legal drive number was specified so branch to N101 to continue. | |
EE12 | 10 05 | BPL $EE19 | ||
EE14 | A9 33 | LDA #$33 | Load .A with $33 to indicate a BAD DRIVE NUMBER and JMP to CMDERR ($C1C8). | |
EE16 | 4C C8 C1 | JMP $C1C8 | ||
N101 | EE19 | 29 01 | AND #$01 | AND the drive number (in .A) with $01 to mask off the non drive bits and store the result as the current drive in DRVNUM ($7F) . |
EE1B | 85 7F | STA $7F | ||
EE1D | 20 00 C1 | JSR $C100 | JSR to SETLDS ($C100) to turn on the drive active LED. | |
EE20 | A5 7F | LDA $7F | Load .A with the drive number from DRVNUM ($7F). multiply it by 2 (ASL) , and transfer it into .X. | |
EE22 | 0A | ASL | ||
EE23 | AA | TAX | ||
EE24 | AC 7B 02 | LDY $027B | Load .Y with the pointer to the start of the new disk ID in the command buffer from FILTBL+1 ($027B) . | |
EE27 | CC 74 02 | CPY $0274 | Compare the ID pointer in .Y with the length of the command string in CMDSIZ ($0274). If these values are equal, there is no new disk ID. Therefore this must be a short new so branch to N108. | |
EE2A | F0 1A | BEQ $EE46 | ||
EE2C | B9 00 02 | LDA $0200,Y | Transfer new disk ID from the command buffer CMDBUF,Y ($0200, Y) and CMDBUF+1,Y ($0201, Y) to the master disk ID area DSKID,X ($12, X) and DSKID+1,X ($13, X). | |
EE2F | 95 12 | STA $12,X | ||
EE31 | B9 01 02 | LDA $0201,Y | ||
EE34 | 95 13 | STA $13,X | ||
EE36 | 20 07 D3 | JSR $D307 | JSR to CLRCHN ($D307) to clear all channels while formatting. | |
EE39 | A9 01 | LDA #$01 | Store $01 into TRACK ($80) as first track to do. | |
EE3B | 85 80 | STA $80 | ||
EE3D | 20 C6 C8 | JSR $C8C6 | JSR to FORMAT ($C8C6) to set up JMP command in buffer that points to the formatting routine to be used by the disk controller. | |
EE40 | 20 05 F0 | JSR $F005 | JSR to CLRBAM ($F005) to clear the BAM. | |
EE43 | 4C 56 EE | JMP $EE56 | JMP to N110 ($EE56) to continue. | |
Clear directory only |
||||
N108 | EE46 | 20 42 D0 | JSR $D042 | JSR to INITDR ($D042) to init. the drive |
EE49 | A6 7F | LDX $7F | Load .X with the drive number from DRVNUM ($7F) . | |
EE4B | BD 01 01 | LDA $0101,X | Load .A with the DOS version number as given in the BAM, DSKVER,X ($0101, X) and compare it with the 1541 DOS version number ($41) from VERNUM ($FED5). If the version numbers match, branch to N110. | |
EE4E | CD D5 FE | CMP $FED5 | ||
EE51 | F0 03 | BEQ $EE56 | ||
EE53 | 4C 72 D5 | JMP $D572 | DOS versions do not match so JMP to VNERR ($D572) to abort. | |
N110 | EE56 | 20 B7 EE | JSR $EEB7 | JSR to NEWMAP ($EEB7) to create a new BAM. |
EE59 | A5 F9 | LDA $F9 | Load .A with the current job code from JOBNUM ($F9) and transfer it to .Y. | |
EE5B | A8 | TAY | ||
EE5C | 0A | ASL | Multiply the job code in .A by 2 (ASL) and transfer the result to .X. | |
EE5D | AA | TAX | ||
EE5E | AD 88 FE | LDA $FE88 | Load .A with $90, the offset of the disk name in the BAM from DSKNAM ($FE88) and store this pointer in BUFTAB,X ($99, X). | |
EE61 | 95 99 | STA $99,X | ||
EE63 | AE 7A 02 | LDX $027A | Load .X with the buffer number from FILTBL ($027A). load .Y with $27 (the name length) and JSR to TRNAME ($C66E) to transfer the new disk name from the command buffer into the BAM area. | |
EE66 | A9 1B | LDA #$1B | ||
EE68 | 20 6E C6 | JSR $C66E | ||
EE6B | A0 12 | LDY #$12 | Load .Y with $12 (position of disk ID) . | |
EE6D | A6 7F | LDX $7F | Load .X with the drive number from DRVNUM ($7F) and copy the DOS version number ($41) from VERNUM ($FED5) into DSKVER,X ($0101, X) . | |
EE6F | AD D5 FE | LDA $FED5 | ||
EE72 | 9D 01 01 | STA $0101,X | ||
EE75 | 8A | TXA | Transfer the drive number from .X to .A, multiply it by 2 (ASL). and transfer the result back into .X. | |
EE76 | 0A | ASL | ||
EE77 | AA | TAX | ||
EE78 | B5 12 | LDA $12,X | Transfer the first disk ID character from DSKID,X ($12, X) into (DIRBUF) ,Y ($94) ,Y. Increment .Y. | |
EE7A | 91 94 | STA ($94),Y | ||
EE7C | C8 | INY | ||
EE7D | B5 13 | LDA $13,X | Transfer the second disk ID character from DSKID+1,X ($13, X) into (DIRBUF) ,Y ($94) ,Y. Increment .Y twice. | |
EE7F | 91 94 | STA ($94),Y | ||
EE81 | C8 | INY | ||
EE82 | C8 | INY | ||
EE83 | A9 32 | LDA #$32 | Store the directory DOS version ($32; ASCII 2) into (DIRBUF) ,Y; ($94), Y. | |
EE85 | 91 94 | STA ($94),Y | ||
EE87 | C8 | INY | Increment .Y. | |
EE88 | AD D5 FE | LDA $FED5 | Transfer the format type ($41; ASCII A) from VERNUM ($FED5) into (DIRBUF) ,Y ($94) ,Y. | |
EE8B | 91 94 | STA ($94),Y | ||
EE8D | A0 02 | LDY #$02 | Load .Y with $02 so it points to the third byte in the BAM and store the format type ($41; in .A) into the BAM at (BMPNT) ,Y; ($6D),Y. | |
EE8F | 91 6D | STA ($6D),Y | ||
EE91 | AD 85 FE | LDA $FE85 | Transfer the directory track number, $12 from DIRTRK ($FE85) into TRACK ($80) . | |
EE94 | 85 80 | STA $80 | ||
EE96 | 20 93 EF | JSR $EF93 | JSR to USEDTS ($EF93) to mark track 18 sector as used in the BAM. | |
EE99 | A9 01 | LDA #$01 | Set SECTOR ($81) to $01. | |
EE9B | 85 81 | STA $81 | ||
EE9D | 20 93 EF | JSR $EF93 | JSR to USEDTS ($EF93) to mark track 18 sector 1 as used in the BAM. | |
EEA0 | 20 FF EE | JSR $EEFF | JSR to SCRBAM ($EEFF) to write out the new BAM to disk. | |
EEA3 | 20 05 F0 | JSR $F005 | JSR to CLRBAM ($F005) to set all of BAM area to $00. | |
EEA6 | A0 01 | LDY #$01 | Load .Y with $01 and store $FF as the first directory block's sector link in (BMPNT) ,Y; ($6D) ,Y. | |
EEA8 | A9 FF | LDA #$FF | ||
EEAA | 91 6D | STA ($6D),Y | ||
EEAC | 20 64 D4 | JSR $D464 | JSR to DRTWRT ($D464) to write out the new directory block to disk. | |
EEAF | C6 81 | DEC $81 | Decrement the sector number (from $01 to $00) in SECTOR ($81) and JSR to DRTRD ($D460) to read the BAM back into RAM. | |
EEB1 | 20 60 D4 | JSR $D460 | ||
EEB4 | 4C 94 C1 | JMP $C194 | Terminate command with a JMP to ENDCMD ($C194) . | |
Create a new BAM map |
||||
NEWMAP | EEB7 | 20 D1 F0 | JSR $F0D1 | JSR to CLNBAM ($F0D1) to set entire BAM area to $00's. |
EEBA | A0 00 | LDY #$00 | Using .Y as a pointer, store $12 (#18) and $01 as the track and sector link in (BMPNT) ,Y; ($6D) ,Y; as the first two bytes of the new BAM. | |
EEBC | A9 12 | LDA #$12 | ||
EEBE | 91 6D | STA ($6D),Y | ||
EEC0 | C8 | INY | ||
EEC1 | 98 | TYA | ||
EEC2 | 91 6D | STA ($6D),Y | ||
EEC4 | C8 | INY | Increment .Y until it is $04. | |
EEC5 | C8 | INY | ||
EEC6 | C8 | INY | ||
NM10 | EEC7 | A9 00 | LDA #$00 | Zero the area to be used to manipulate the BAM map bits, TO ($6F). Tl ($70), and T2 ($71) . |
EEC9 | 85 6F | STA $6F | ||
EECB | 85 70 | STA $70 | ||
EECD | 85 71 | STA $71 | ||
EECF | 98 | TYA | Transfer the byte from .Y into .A and divide it by 4 (2 * LSR) to find the track number. | |
EED0 | 4A | LSR | ||
EED1 | 4A | LSR | ||
EED2 | 20 4B F2 | JSR $F24B | JSR to MAXSEC ($F24B) to calculate the maximum sector number for this track and store this value as the number of sectors free on this track in (BMPNT) ,Y ($6D) ,Y. | |
EED5 | 91 6D | STA ($6D),Y | ||
EED7 | C8 | INY | Increment .Y. Transfer the maximum sector number from .A into .X. | |
EED8 | AA | TAX | ||
NM20 | EED9 | 38 | SEC | Set the carry flag (this 1 bit will indicate that this sector is free) and rotate this bit from the carry into the bit map area (TO/1/2) using ROL TO, ROL Tl, and ROL T2.
|
EEDA | 26 6F | ROL $6F | ||
EEDC | 26 70 | ROL $70 | ||
EEDE | 26 71 | ROL $71 | ||
EEE0 | CA | DEX | Decrement the sector count in .X. If the resulting .X value is not $00, there are more to do so branch back to NM20. | |
EEE1 | D0 F6 | BNE $EED9 | ||
NM30 | EEE3 | B5 6F | LDA $6F,X | Transfer the bit map for this track from T0,X ($6F,X) to the "BAM area (BMPNT) ,Y; ($6D,Y). Increment .Y and .X. If the new .X value is not $03, we have more to transfer so branch back to NM30. |
EEE5 | 91 6D | STA ($6D),Y | ||
EEE7 | C8 | INY | ||
EEE8 | E8 | INX | ||
EEE9 | E0 03 | CPX #$03 | ||
EEEB | 90 F6 | BCC $EEE3 | ||
EEED | C0 90 | CPY #$90 | Compare the .Y value to $90. If it is less than $90, we have more tracks to do so branch back to NM10. | |
EEEF | 90 D6 | BCC $EEC7 | ||
EEF1 | 4C 75 D0 | JMP $D075 | JMP to NFCALC ($D075) to calculate the number of blocks free. | |
Write out BAM to the drive specified in LSTJOB |
||||
MAPOUT | EEF4 | 20 93 DF | JSR $DF93 | JSR to GETACT ($DF93) to find the active buffer number (returned in .A) . |
EEF7 | AA | TAX | Transfer the buffer number to .X. | |
EEF8 | BD 5B 02 | LDA $025B,X | Load .A with the job code for the last- job from LSTJOB, X ($025B,X). AND it with $01 to mask off the non-drive bits, and store the result in DRVNUM ($7F) . | |
EEFB | 29 01 | AND #$01 | ||
EEFD | 85 7F | STA $7F | ||
Write out BAM to the drive specified in DRVNUM |
||||
SCRBAM | EEFF | A4 7F | LDY $7F | Load .Y with the drive number from DRVNUM ($7F) . |
EF01 | B9 51 02 | LDA $0251,Y | Load .A with the BAM-dirty flag from MDIRTY,Y ($0251, Y). If the flag is not $00, the BAM is dirty (the copy in RAM does NOT match the copy on disk) so branch to SB10 to write it out to disk. | |
EF04 | D0 01 | BNE $EF07 | ||
EF06 | 60 | RTS | BAM is clean so there is no reason to write it out. Terminate routine with an RTS. | |
SB10 | EF07 | A9 00 | LDA #$00 | Zero the BAM-dirty flag in MDIRTY,Y ($0251, Y) . |
EF09 | 99 51 02 | STA $0251,Y | ||
EF0C | 20 3A EF | JSR $EF3A | JSR to SETBPT ($EF3A) to set up the pointer to the BAM. | |
EF0F | A5 7F | LDA $7F | Load .A with the drive number from DRVNUM ($7F). multiply it by 2 (ASL) , and save the result onto the stack. | |
EF11 | 0A | ASL | ||
EF12 | 48 | PHA | ||
EF13 | 20 A5 F0 | JSR $F0A5 | JSR to PUTBAM ($F0A5) to put the memory images to the BAM. | |
EF16 | 68 | PLA | Pull the (drive number x 2) off the stack, clear the carry flag, add $01, and JSR to PUTBAM ($F0A5) to put the memory images to the BAM. | |
EF17 | 18 | CLC | ||
EF18 | 69 01 | ADC #$01 | ||
EF1A | 20 A5 F0 | JSR $F0A5 | ||
Verify that the block count for the track matches the bit map for the track. |
||||
EF1D | A5 80 | LDA $80 | Load .A from TRACK ($80) and push the track number onto the stack. | |
EF1F | 48 | PHA | ||
EF20 | A9 01 | LDA #$01 | Load .A with $01 and store it in TRACK. | |
EF22 | 85 80 | STA $80 | ||
SB20 | EF24 | 0A | ASL | Multiply the track number in .A by 4 (2 x ASL) and store the result as the lo byte of the buffer pointer in BMPNT ($6D) . |
EF25 | 0A | ASL | ||
EF26 | 85 6D | STA $6D | ||
EF28 | 20 20 F2 | JSR $F220 | JSR to AVCK ($F220) to check that the blocks free for the track agrees with the bit map. | |
EF2B | E6 80 | INC $80 | Increment the track count in TRACK ($80) If the new count is less than the the maximum track number (#36). branch back to SB20 to check the next track. | |
EF2D | A5 80 | LDA $80 | ||
EF2F | CD D7 FE | CMP $FED7 | ||
EF32 | 90 F0 | BCC $EF24 | ||
EF34 | 68 | PLA | Pull the original track number off the stack and restore it into TRACK ($80) . | |
EF35 | 85 80 | STA $80 | ||
EF37 | 4C 8A D5 | JMP $D58A | JMP to DOWRIT ($D58A) to write out the BAM to disk. | |
Read in the BAM, if not already in RAM, and set the pointers to the BAM |
||||
SETBPT | EF3A | 20 0F F1 | JSR $F10F | JSR to BAM2A ($F10F) to get the BAM channel number in .A (drO = 6). Transfer the channel number into .X. |
EF3D | AA | TAX | ||
EF3E | 20 DF F0 | JSR $F0DF | JSR to REDBAM ($F0DF) to read in the BAM if not already in memory. | |
EF41 | A6 F9 | LDX $F9 | Load .X with the buffer number used for the read from JOBNUM ($F9). | |
EF43 | BD E0 FE | LDA $FEE0,X | Set the hi byte of the pointer to the BAM in BMPNT+1 ($6E) using the hi byte pointer value for the buffer from BUFIND,X ($FEE0,X) . | |
EF46 | 85 6E | STA $6E | ||
EF48 | A9 00 | LDA #$00 | Set the lo byte of the pointer to the BAM in BMPNT ($6D) to $00. | |
EF4A | 85 6D | STA $6D | ||
EF4C | 60 | RTS | Terminate routine with an RTS. | |
Get the number of blocks free on the drive specified in DRVNUM |
||||
NUMFRE | EF4D | A6 7F | LDX $7F | Load .X with the drive number from DRVNUM ($7F) . |
EF4F | BD FA 02 | LDA $02FA,X | Transfer the lo byte of the number of blocks free from ND3L,X ($02FA,X) into NBTEMP ($0272) . | |
EF52 | 8D 72 02 | STA $0272 | ||
EF55 | BD FC 02 | LDA $02FC,X | Transfer the hi byte of the number of blocks free from NDBH,X ($02FC,X) into NBTEMP+1 ($0273) . | |
EF58 | 8D 73 02 | STA $0273 | ||
EF5B | 60 | RTS | Terminate routine with an RTS. | |
Free the block specified in TRACK and SECTOR as free in the BAM |
||||
WFREE | EF5C | 20 F1 EF | JSR $EFF1 | JSR to FIXBAM ($EFF1) to write out the BAM the value in WBAM indicates that it is needed. |
FRETS | EF5F | 20 CF EF | JSR $EFCF | JSR to FREUSE ($EFCF) to calculate the index to the BAM entry that contains the desired TRACK and SECTOR. On return .Y points to the entry and .X points to the bit within the entry. |
FRETS2 | EF62 | 38 | SEC | Set the carry flag (the flag for no action required) . |
EF63 | D0 22 | BNE $EF87 | If Z flag is NOT set, the desired TRACK and SECTOR is already free in the BAM so branch to FRERTS to exit. | |
EF65 | B1 6D | LDA ($6D),Y | Load .A with BAM entry from (BMPNT) ,Y ($6D) ,Y, OR it with the bit map mask from BMASK,X ($EFE9,X) to turn on (free) the bit that corresponds to the desired block, and store the result back into (BMPNT) ,Y; ($6D) ,Y. | |
EF67 | 1D E9 EF | ORA $EFE9,X | ||
EF6A | 91 6D | STA ($6D),Y | ||
EF6C | 20 88 EF | JSR $EF88 | JSR to DTYBAM ($EF88) to set the dirty BAM flag (BAM in RAM and BAM on disk do not match) . | |
EF6F | A4 6F | LDY $6F | Load .Y with the pointer to the number of blocks free for the track from TEMP ($6F) and clear the carry flag. | |
EF71 | 18 | CLC | ||
EF72 | B1 6D | LDA ($6D),Y | Load .A with the blocks free for the track from (BMPNT) ,Y; ($6D) ,Y, add 1, and store the result back into (BMPNT) ,Y | |
EF74 | 69 01 | ADC #$01 | ||
EF76 | 91 6D | STA ($6D),Y | ||
EF78 | A5 80 | LDA $80 | Load .A with the TRACK ($80) number of the block we just freed. If it is on the directory track (#18). branch to USE10 ($EFBA) . | |
EF7A | CD 85 FE | CMP $FE85 | ||
EF7D | F0 3B | BEQ $EFBA | ||
EF7F | FE FA 02 | INC $02FA,X | Increment the lo byte of the count of the total number of blocks free on the disk, NDBL,X ($02FA,X) by 1. If the result is NOT $00, branch to FRERTS | |
EF82 | D0 03 | BNE $EF87 | ||
EF84 | FE FC 02 | INC $02FC,X | Increment the hi byte of the count of the total number of blocks free on the disk, NDBH,X ($02FC,X) by 1. | |
FRERTS | EF87 | 60 | RTS | Terminate routine with an RTS. |
Set dirty-BAM flagIndicates that the copy of the BAM in disk RAM does not match the disk copy. |
||||
DTYBAM | EF88 | A6 7F | LDX $7F | Load .X with the current drive number from DRVNUM ($7F) . |
EF8A | A9 01 | LDA #$01 | Store a $01 into the dirty BAM flag in MDIRTY,X ($0251) . | |
EF8C | 9D 51 02 | STA $0251,X | ||
EF8F | 60 | RTS | Terminate routine with an RTS. | |
Mark the block specified in TRACK and SECTOR as USED in the BAM |
||||
WUSED | EF90 | 20 F1 EF | JSR $EFF1 | JSR to FIXBAM ($EFF1) to write out the BAM the value in WBAM indicates that it is needed. |
USEDTS | EF93 | 20 CF EF | JSR $EFCF | JSR to FREUSE ($EFCF) to calculate the index to the BAM entry that contains the desired TRACK and SECTOR. On return .Y points to the entry and .X points to the bit within the entry. |
EF96 | F0 36 | BEQ $EFCE | If Z flag is set, the desired TRACK and SECTOR is already marked as USED in the BAM so branch to USERTS to exit. | |
EF98 | B1 6D | LDA ($6D),Y | Load .A with BAM entry from (BMPNT) ,Y ($6D) ,Y. EOR it with the bit map mask from BMASK,X ($EFE9,X) to zero (in use) the bit that corresponds to the desired block, and store the result back into (BMPNT) ,Y; ($6D) f Y. | |
EF9A | 5D E9 EF | EOR $EFE9,X | ||
EF9D | 91 6D | STA ($6D),Y | ||
EF9F | 20 88 EF | JSR $EF88 | JSR to DTYBAM ($EF88) to set the dirty BAM flag (BAM in RAM and BAM on disk do not match) . | |
EFA2 | A4 6F | LDY $6F | Load .Y with the pointer to the number of blocks free for the track from TEMP ($6F) . | |
EFA4 | B1 6D | LDA ($6D),Y | Load .A with the blocks free for the track from (BMPNT) ,Y; ($6D) ,Y, set the carry flag, subtract $01, and store the result back into (BMPNT) ,Y. | |
EFA6 | 38 | SEC | ||
EFA7 | E9 01 | SBC #$01 | ||
EFA9 | 91 6D | STA ($6D),Y | ||
EFAB | A5 80 | LDA $80 | Load .A with the TRACK ($80) number of the block we just freed. If it is on the directory track (#18), branch to USE20 ($EFBD) . | |
EFAD | CD 85 FE | CMP $FE85 | ||
EFB0 | F0 0B | BEQ $EFBD | ||
EFB2 | BD FA 02 | LDA $02FA,X | Load .A with the lo byte of the count of the total number of blocks free on the disk, NDBL,X ($02FA,X). If the lo byte is NOT $00, branch to USE10. | |
EFB5 | D0 03 | BNE $EFBA | ||
EFB7 | DE FC 02 | DEC $02FC,X | Decrement the hi byte of the count of the total number of blocks free on the disk, NDBH,X ($02FC,X) by 1. | |
USE10 | EFBA | DE FA 02 | DEC $02FA,X | Decrement the lo byte of the count of the total number of blocks free on the disk, NDBL,X ($02FA,X) by 1. |
USE20 | EFBD | BD FC 02 | LDA $02FC,X | Load .A with the hi byte of the count of the total number of blocks free on the disk, NDBH,X ($02FC,X). If the hi byte is NOT $00, branch to USERTS. |
EFC0 | D0 0C | BNE $EFCE | ||
EFC2 | BD FA 02 | LDA $02FA,X | Load .A with the lo byte of the count of the total number of blocks free on the disk, NDBL,X ($02FA,X). If the lo byte is greater than 2, branch to USERTS. | |
EFC5 | C9 03 | CMP #$03 | ||
EFC7 | B0 05 | BCS $EFCE | ||
EFC9 | A9 72 | LDA #$72 | Load .A with $72 to indicate a DISK FULL error and JSR to ERRMSG ($E6C7) . | |
EFCB | 20 C7 E6 | JSR $E6C7 | ||
USERTS | EFCE | 60 | RTS | Terminate routine with an RTS. |
Calculate index into the BAM for FRETS and USEDTS.
|
||||
FREUSE | EFCF | 20 11 F0 | JSR $F011 | JSR to SETBAM ($F011) to set BAM image in memory. On return .Y contains a pointer to the start of the bit map for the desired track. |
EFD2 | 98 | TYA | Transfer the pointer from .Y to .A. | |
FREUS2 | EFD3 | 85 6F | STA $6F | Store the pointer from .A into TEMP ($6F) . |
FREUS3 | EFD5 | A5 81 | LDA $81 | Load .A with the desired sector number from SECTOR ($81) and do three LSR's to divide the sector number by 8 to find out which of the three bytes for this track the sector is in. |
EFD7 | 4A | LSR | ||
EFD8 | 4A | LSR | ||
EFD9 | 4A | LSR | ||
EFDA | 38 | SEC | Set the carry flag, add the pointer to the start of the track from TEMP ($6F) to the sector index (0/1/2) in .A, and transfer the result to .Y. | |
EFDB | 65 6F | ADC $6F | ||
EFDD | A8 | TAY | ||
EFDE | A5 81 | LDA $81 | Load .A with the desired sector number from SECTOR ($81), AND the sector number with $07 to find the bit position that corresponds to that sector, and transfer the result into .X. | |
EFE0 | 29 07 | AND #$07 | ||
EFE2 | AA | TAX | ||
EFE3 | B1 6D | LDA ($6D),Y | Load .A with the BAM byte that contains the bit for the desired block from (BMPNT) ,Y; ($6D) ,Y, and AND it with the bit map for the appropriate bit from BMASK, X ($EFE9,X) to set the Z flag. | |
EFE5 | 3D E9 EF | AND $EFE9,X | ||
EFE8 | 60 | RTS | Terminate routine with an RTS. | |
Bit mask table $EFE9-EFF0 |
||||
BMASK | EFE9 | 01 | .BYTE $01 1 | |
EFEA | 02 | .BYTE $02 2 | ||
EFEB | 04 | .BYTE $04 4 | ||
EFEC | 08 | .BYTE $08 8 | ||
EFED | 10 | .BYTE $10 16 | ||
EFEE | 20 | .BYTE $20 32 | ||
EFEF | 40 | .BYTE $40 64 | ||
EFF0 | 80 | .BYTE $80 128 | ||
Write out BAM to disk if value in WBAM indicates that it is necessary. |
||||
FIXBAM | EFF1 | A9 FF | LDA #$FF | Load .A with $FF and BIT this value with the value in WBAM ($02F9) . |
EFF3 | 2C F9 02 | BIT $02F9 | ||
EFF6 | F0 0C | BEQ $F004 | If Z flag set (WBAM was $00) branch to FBAM10 to exit. | |
EFF8 | 10 0A | BPL $F004 | If N flag clear (bit 7 of WBAM was 0) branch to FBAM10 to exit. | |
EFFA | 70 08 | BVS $F004 | If V flag set (bit 6 of WBAM was 0) branch to FBAM10 to exit. | |
EFFC | A9 00 | LDA #$00 | Set WBAM ($02F9) to $00 and JSR to DOWRIT ($D58A) to write BAM to disk. | |
EFFE | 8D F9 02 | STA $02F9 | ||
F001 | 4C 8A D5 | JMP $D58A | ||
FBAM10 | F004 | 60 | RTS | Terminate routine with an RTS. |
Zero the BAM area |
||||
CLRBAM | F005 | 20 3A EF | JSR $EF3A | JSR to SETBPT ($EF3A) to to set the pointers to the BAM. |
F008 | A0 00 | LDY #$00 | Zero .Y and .A. | |
F00A | 98 | TYA | ||
CLB1 | F00B | 91 6D | STA ($6D),Y | Loop, using .Y as an index, to store $00' s in all 256 locations in the BAM buffer. |
F00D | C8 | INY | ||
F00E | D0 FB | BNE $F00B | ||
F010 | 60 | RTS | Terminate routine with an RTS. | |
Set BAM image in memory |
||||
SETBAM | F011 | A5 6F | LDA $6F | Save the values of T0 ($6F) and T1 ($70) onto the stack so we can use this as a work area. |
F013 | 48 | PHA | ||
F014 | A5 70 | LDA $70 | ||
F016 | 48 | PHA | ||
F017 | A6 7F | LDX $7F | Load .X with the current drive number from DRVNUM ($7F). Load .A with the drive status for this drive from NODRV,X ($FF,X). If the drive status is $00, we have a functioning drive so branch to SBM10 to continue. | |
F019 | B5 FF | LDA $FF,X | Load .A with $74 to indicate a DRIVE NOT READY error and JSR to CMDER3 ($E648). | |
F01B | F0 05 | BEQ $F022 | ||
F01D | A9 74 | LDA #$74 | ||
F01F | 20 48 E6 | JSR $E648 | ||
SBM10 | F022 | 20 0F F1 | JSR $F10F | JSR to BAM2A ($ F10F) to load .A with the channel number and .X with the drive #. |
F025 | 85 6F | STA $6F | Transfer the channel number (in .A) into TO ($6F). | |
F027 | 8A | TXA | Transfer the drive number from .X into .A, multiply itby 2 (ASL). store the result in Tl ($70) and in .X. | |
F028 | 0A | ASL | ||
F029 | 85 70 | STA $70 | ||
F02B | AA | TAX | ||
F02C | A5 80 | LDA $80 | ||
F02E | DD 9D 02 | CMP $029D,X | Load .A with the current track number from TRACK ($80) and compare it with the track valuegiven in the BAM track table, TBAM,X ($029D,X). If the values match, the BAM is in the correct area of memory so branch to SBM30. | |
F031 | F0 0B | BEQ $F03E | ||
F033 | E8 | INX | Increment .X by 1 and store the result in Tl ($70). Note that .X now points to the alternate BAM channel. | |
F034 | 86 70 | STX $70 | ||
F036 | DD 9D 02 | CMP $029D,X | Compare the current track value (in .A) with the contents of the BAM track table TBAM,X ($029D,X) for the alternate BAM location. If the value match, the BAM is in an appropriate location so branch to SBM3 0. | |
F039 | F0 03 | BEQ $F03E | ||
F03B | 20 5B F0 | JSR $F05B | JSR to SWAP ($F05B) to read in the BAM if necessary and move it to the correct area of the disk RAM. | |
SBM30 | F03E | A5 70 | LDA $70 | Load .A with the BAM channel number from T1 ($70). |
F040 | A6 7F | LDX $7F | Load .X with the current drive number from DRVNUM ($7F) . | |
F042 | 9D 9B 02 | STA $029B,X | Store the channel number (in .A) into UBAM,X ($029B,X) to set the last channel used pointer. | |
F045 | 0A | ASL | Multiply the channel number (in .A) by four (2 x ASL), clear the carry, and add $A1, the lo byte of the pointer, to the start of the BAM ($02A1). Store the result into the lo byte of the BAM pointer, BMPNT ($6D) . | |
F046 | 0A | ASL | ||
F047 | 18 | CLC | ||
F048 | 69 A1 | ADC #$A1 | ||
F04A | 85 6D | STA $6D | ||
F04C | A9 02 | LDA #$02 | Load .A with $02, the hi byte of the pointer to the start of the BAM, add $00 to add in the carry (if any) from the previous addition, and store the result- as the hi byte of the BAM pointer, BMPNT+1 ($6E) . | |
F04E | 69 00 | ADC #$00 | ||
F050 | 85 6E | STA $6E | ||
F052 | A0 00 | LDY #$00 | Zero .Y. | |
F054 | 68 | PLA | Pull the original values of Tl ($70) and TO ($6F) off the stack and store them back in their original locations. | |
F055 | 85 70 | STA $70 | ||
F057 | 68 | PLA | ||
F058 | 85 6F | STA $6F | ||
F05A | 60 | RTS | Terminate routine with an RTS. | |
Swap images of the BAM |
||||
SWAP | F05B | A6 6F | LDX $6F | Load .X with the index into the buffer from TO ($6F) and JSR to REDBAM ($F0DF) to read the BAM if not already in RAM. |
F05D | 20 DF F0 | JSR $F0DF | ||
F060 | A5 7F | LDA $7F | Load .A with the current drive number from DRVNUM ($7F) and transfer the drive number into .X. | |
F062 | AA | TAX | ||
F063 | 0A | ASL | Multiply the drive number in .A by two (ASL). OR it with the least used BAM pointer in UBAM,X ($029B,X). EOR it with $01, and AND it with $03. Store the result into Tl ($70) and JSR to PUTBAM ($F0A5) to put the memory image into the BAM. | |
F064 | 1D 9B 02 | ORA $029B,X | ||
F067 | 49 01 | EOR #$01 | ||
F069 | 29 03 | AND #$03 | ||
F06B | 85 70 | STA $70 | ||
F06D | 20 A5 F0 | JSR $F0A5 | ||
F070 | A5 F9 | LDA $F9 | Load .A with the buffer number from JOBNUM ($F9), multiply it by two (ASL), and transfer the result into .X. | |
F072 | 0A | ASL | ||
F073 | AA | TAX | ||
F074 | A5 80 | LDA $80 | Load .A with the track number from TRACK ($80), multiply it by four (2 x ASL), and store the result as the lo byte of the pointer in BUFTAB,X ($99, X). | |
F076 | 0A | ASL | ||
F077 | 0A | ASL | ||
F078 | 95 99 | STA $99,X | ||
F07A | A5 70 | LDA $70 | Load .A with the value from Tl ($70) , multiply it by four (2 x ASL), and transfer the result into .Y. | |
F07C | 0A | ASL | ||
F07D | 0A | ASL | ||
F07E | A8 | TAY | ||
SWAP3 | F07F | A1 99 | LDA ($99,X) | Transfer one byte of the BAM from its position in RAM, (BUFTAB,X) ($99, X), to its proper position BAM,Y ($02A1,Y). |
F081 | 99 A1 02 | STA $02A1,Y | ||
F084 | A9 00 | LDA #$00 | Zero the memory location that held the BAM byte (BUFTAB,X); ($99, X). | |
F086 | 81 99 | STA ($99,X) | ||
F088 | F6 99 | INC $99,X | Increment the lo byte of the pointer to the original BAM image BUFTAB,X ($99, X). | |
F08A | C8 | INY | Increment .Y, the pointer to the new BAM image. Transfer this value into .A, AND it with $03 to mask off the high order bits, and if the result is not $00, branch back to SWAP3 to move the next byte. | |
F08B | 98 | TYA | ||
F08C | 29 03 | AND #$03 | ||
F08E | D0 EF | BNE $F07F | ||
F090 | A6 70 | LDX $70 | Load .X with the drive number from Tl ($70). Load .A with the current track number from TRACK ($80) and store the track number into TBAM,X ($029D,X) to set the track number for the image. | |
F092 | A5 80 | LDA $80 | ||
F094 | 9D 9D 02 | STA $029D,X | ||
F097 | AD F9 02 | LDA $02F9 | Load .A with the write-BAM flag from WBAM ($02F9). If the flag is non-zero, branch to SWAP4 so we don't write out the BAM now. | |
F09A | D0 03 | BNE $F09F | ||
F09C | 4C 8A D5 | JMP $D58A | JMP to DOWRIT ($D58A) to write out the BAM to disk and terminate the routine. | |
SWAP4 | F09F | 09 80 | ORA #$80 | OR the write-BAM flag (in .A) with $80 to indicate that a write of the BAM is pending and store the result back into WBAM ($02F9) . |
F0A1 | 8D F9 02 | STA $02F9 | ||
F0A4 | 60 | RTS | Terminate routine with an RTS. | |
Transfer memory image of BAM into the correct position in disk RAM |
||||
PUTBAM | F0A5 | A8 | TAY | Transfer the pointer in .A into .Y. |
F0A6 | B9 9D 02 | LDA $029D,Y | Load .A with the track number of the BAM from TBAM,Y ($029D,Y). If the track number is $00. there is no BAM image in RAM so branch to SWAP2. | |
F0A9 | F0 25 | BEQ $F0D0 | ||
F0AB | 48 | PHA | Save the track number onto the stack. | |
F0AC | A9 00 | LDA #$00 | Zero the track flag in TBAM,Y ($029D,Y). | |
F0AE | 99 9D 02 | STA $029D,Y | ||
F0B1 | A5 F9 | LDA $F9 | Load .A with the buffer number from JOBNUM ($F9). multiply it by two (ASL) , and transfer the result into .X. | |
F0B3 | 0A | ASL | ||
F0B4 | AA | TAX | ||
F0B5 | 68 | PLA | Pull the track number off the stack, multiply it by four (2 x ASL). and store the result as the lo byte of the pointer in BUFTAB,X ($99, X) . | |
F0B6 | 0A | ASL | ||
F0B7 | 0A | ASL | ||
F0B8 | 95 99 | STA $99,X | ||
F0BA | 98 | TYA | Transfer the pointer in .Y into .A, multiply it by four (2 x ASL). and transfer the result back into .Y. | |
F0BB | 0A | ASL | ||
F0BC | 0A | ASL | ||
F0BD | A8 | TAY | ||
SWAP1 | F0BE | B9 A1 02 | LDA $02A1,Y | Transfer one byte of the BAM image from BAM,Y ($02A1) to (BUFTAB,X); ($99, X). |
F0C1 | 81 99 | STA ($99,X) | ||
F0C3 | A9 00 | LDA #$00 | Zero the memory location that held the BAM byte BAM,X ($02A1,X). | |
F0C5 | 99 A1 02 | STA $02A1,Y | ||
F0C8 | F6 99 | INC $99,X | Increment the lo byte of the pointer to the original BAM image BUFTAB,X ($99, X). | |
F0CA | C8 | INY | Increment .Y, the pointer to the new BAM image. Transfer this value into .A, AND it with $03 to mask off the high order bits, and if the result is not $00, branch back to SWAP1 to move the next- byte. | |
F0CB | 98 | TYA | ||
F0CC | 29 03 | AND #$03 | ||
F0CE | D0 EE | BNE $F0BE | ||
SWAP2 | F0D0 | 60 | RTS | Terminate the routine with an RTS. |
Zero the track number for BAM images |
||||
CLNBAM | F0D1 | A5 7F | LDA $7F | Load .A with the drive number from TRACK ($80). multiply it by two (ASL) , and transfer the result into .X. |
F0D3 | 0A | ASL | ||
F0D4 | AA | TAX | ||
F0D5 | A9 00 | LDA #$00 | Zero .A and store $00 as the track # for the BAM image in TBAM,X ($029D,X). | |
F0D7 | 9D 9D 02 | STA $029D,X | ||
F0DA | E8 | INX | Increment .X and store $00 as the track# for the BAM image in TBAM,X ($029D,X) . | |
F0DB | 9D 9D 02 | STA $029D,X | ||
F0DE | 60 | RTS | Terminate the routine with an RTS, | |
Read BAM from disk if not already in RAM |
||||
REDBAM | F0DF | B5 A7 | LDA $A7,X | Load .A with the value from BUF0,X and compare it with $FF. If it is not $FF, the BAM is in memory so branch to RBM20. |
F0E1 | C9 FF | CMP #$FF | ||
F0E3 | D0 25 | BNE $F10A | ||
F0E5 | 8A | TXA | Transfer the channel number from .X into .A and save it onto the stack. | |
F0E6 | 48 | PHA | ||
F0E7 | 20 8E D2 | JSR $D28E | JSR to GETBUF ($D28E) to find a free buffer. On return transfer the buffer number from .A into .X. | |
F0EA | AA | TAX | ||
F0EB | 10 05 | BPL $F0F2 | If a buffer was found (bit 7 of buffer number not set). branch to RBM10. | |
F0ED | A9 70 | LDA #$70 | Load .A with $70 to indicate a NO CHANNEL ERROR and JSR to CMDERR ($C1C8) . | |
F0EF | 20 C8 C1 | JSR $C1C8 | ||
RBM10 | F0F2 | 86 F9 | STX $F9 | Store the buffer number assigned (in .X) into JOBNUM ($F9) . |
F0F4 | 68 | PLA | Pull the channel number off the stack and transfer it into .Y. | |
F0F5 | A8 | TAY | ||
F0F6 | 8A | TXA | Transfer the buffer number from .X to .A, OR it with $80 to set it as inactive for stealing, and store the result into BUF0,Y ($00A7,Y) . | |
F0F7 | 09 80 | ORA #$80 | ||
F0F9 | 99 A7 00 | STA $00A7,Y | ||
F0FC | 0A | ASL | Multiply the buffer number (in .A) by two (ASL) and transfer the result into .X. | |
F0FD | AA | TAX | ||
F0FE | AD 85 FE | LDA $FE85 | Load .A with the directory track number (#18) from DIRTRK ($FE85) and store it in the header table at HDRS,X ($06, X). | |
F101 | 95 06 | STA $06,X | ||
F103 | A9 00 | LDA #$00 | Store $00 as the BAM sector number in the header table at HDRS+1,X ($07, X). | |
F105 | 95 07 | STA $07,X | ||
F107 | 4C 86 D5 | JMP $D586 | JMP to DOREAD ($D58 6) to read in the BAM and terminate routine. | |
RBM20 | F10A | 29 0F | AND #$0F | AND the channel number (in .A) with $0F and store the result in JOBNUM ($F9) to set the BAM's job number. |
F10C | 85 F9 | STA $F9 | ||
F10E | 60 | RTS | Terminate routine with an RTS. | |
Load .A with the channel # for the BAM |
||||
BAM2A | F10F | A9 06 | LDA #$06 | Load .A with $06, the BAM's channel # |
F111 | A6 7F | LDX $7F | Load .X with the current drive number from DRVNUM ($7F). If the drive number is not $00, branch to B2X10. | |
F113 | D0 03 | BNE $F118 | ||
F115 | 18 | CLC | Clear the carry flag and add $07 to find the BAM channel number for drive #1. | |
F116 | 69 07 | ADC #$07 | ||
B2X10 | F118 | 60 | RTS | Terminate routine with an RTS. |
BAAM2X | F119 | 20 0F F1 | JSR $F10F | Load .X with the channel # for the BAM JSR TO BAM2A ($F10F) to load .A with the BAM's channel number. |
F11C | AA | TAX | Transfer the channel # from .A to .X. | |
F11D | 60 | RTS | Terminate routine with an RTS. | |
Next available track and sectorGiven current track and sector, this routine returns the next available track and sector. |
||||
NXTTS | F11E | 20 3E DE | JSR $DE3E | JSR to GETHDR ($DE3E) to set TRACK and SECTOR from the most recent header. |
F121 | A9 03 | LDA #$03 | Store $03 into TEMP ($6F) . | |
F123 | 85 6F | STA $6F | ||
F125 | A9 01 | LDA #$01 | Load .A with $01, OR it with the value of the write-BAM flag, WBAM ($02F9), and store the result back into WBAM to prevent a write of the BAM. | |
F127 | 0D F9 02 | ORA $02F9 | ||
F12A | 8D F9 02 | STA $02F9 | ||
NXTDS | F12D | A5 6F | LDA $6F | Load .A with the value from TEMP ($6F) and save it onto the stack. |
F12F | 48 | PHA | ||
NXT1 | F130 | 20 11 F0 | JSR $F011 | JSR to SETBAM ($F011) to set the BAM image into memory. |
F133 | 68 | PLA | Pull the original value of TEMP off the stack and store it back in TEMP ($6F) . | |
F134 | 85 6F | STA $6F | ||
F136 | B1 6D | LDA ($6D),Y | Load .A with the BAM value from (BMPNT) ,Y; ($6D,Y). If the value is not $00 (no sectors free). branch to FNDNXT ($F173) . | |
F138 | D0 39 | BNE $F173 | ||
F13A | A5 80 | LDA $80 | Load .A with the current track number from TRACK ($80). If the track number is #18 (directory track). branch to NXTERR to abort. | |
F13C | CD 85 FE | CMP $FE85 | ||
F13F | F0 19 | BEQ $F15A | ||
F141 | 90 1C | BCC $F15F | If the current track is less than #18, branch to NXT2. | |
F143 | E6 80 | INC $80 | Increment the track number in TRACK ($80) | |
F145 | A5 80 | LDA $80 | Compare the value of TRACK to $24 (#36), the maximum track value. If they are not equal, branch to NXT1 to check out this track. | |
F147 | CD D7 FE | CMP $FED7 | ||
F14A | D0 E1 | BNE $F12D | ||
F14C | AE 85 FE | LDX $FE85 | Load .X with $12 (#18). the directory track number from DIRTRK ($FE85) . | |
F14F | CA | DEX | Decrement the track number in .X. | |
F150 | 86 80 | STX $80 | Store the track number (in .X) into TRACK ($80) . | |
F152 | A9 00 | LDA #$00 | Store $00 as the sector number into SECTOR ($81) . | |
F154 | 85 81 | STA $81 | ||
F156 | C6 6F | DEC $6F | Decrement the counter in TEMP ($6F) . | |
F158 | D0 D3 | BNE $F12D | If the count is not $00 yet, branch to NXT1. | |
NXTERR | F15A | A9 72 | LDA #$72 | Load .A with $72 to indicate a DISK FULL error and JSR to CMDERR ($C1C8). |
F15C | 20 C8 C1 | JSR $C1C8 | ||
NXT2 | F15F | C6 80 | DEC $80 | Decrement the track number in TRACK ($80) |
F161 | D0 CA | BNE $F12D | If the value in TRACK is not $00, branch to NXT1 to check out this track. | |
F163 | AE 85 FE | LDX $FE85 | Load .X with $12 (#18). the directory track number from DIRTRK ($FE85) . | |
F166 | E8 | INX | Increment the track number in .X. | |
F167 | 86 80 | STX $80 | Store the track number (in .X) into TRACK ($80) . | |
F169 | A9 00 | LDA #$00 | Store $00 as the sector number into SECTOR ($81) . | |
F16B | 85 81 | STA $81 | ||
F16D | C6 6F | DEC $6F | Decrement the counter in TEMP ($6F) . | |
F16F | D0 BC | BNE $F12D | If the count is not $00 yet, branch to NXT1. | |
F171 | F0 E7 | BEQ $F15A | If the count is $00, branch to NXTERR. | |
Find the optimum next sector on this trackNext sector = Current + change (#10) |
||||
FNDNXT | F173 | A5 81 | LDA $81 | Load .A with the sector number from SECTOR ($81) . |
F175 | 18 | CLC | Clear the carry flag and add the sector increment from SECINC ($69). The normal increment is $0A (#10). It is $03 for the directory track. | |
F176 | 65 69 | ADC $69 | ||
F178 | 85 81 | STA $81 | Store the new sector number into SECTOR. | |
F17A | A5 80 | LDA $80 | Load .A with the current track number from TRACK ($80) and JSR to MAXSEC ($F24B) to find the maximum sector number on this track (returned in .A) . | |
F17C | 20 4B F2 | JSR $F24B | ||
F17F | 8D 4E 02 | STA $024E | Store the maximum sector number into LSTSEC ($024E) and CMD ($024D). | |
F182 | 8D 4D 02 | STA $024D | ||
F185 | C5 81 | CMP $81 | Compare the maximum sector number (in .A) with the new sector value in SECTOR ($81). If the new sector value is less than the maximum, branch to FNDNO. | |
F187 | B0 0C | BCS $F195 | ||
New sector number too big so subtract away the maximum sector number on track. |
||||
F189 | 38 | SEC | Set the carry flag. | |
F18A | A5 81 | LDA $81 | Load .A with the new sector number from SECTOR ($80) . | |
F18C | ED 4E 02 | SBC $024E | Subtract the maximum sector number on this track from LSTSEC ($024E) and store the result into SECTOR ($81). | |
F18F | 85 81 | STA $81 | ||
F191 | F0 02 | BEQ $F195 | If the revised sector number is $00, branch to FNDNO. | |
F193 | C6 81 | DEC $81 | Decrement the revised sector number in SECTOR ($81) by 1. | |
FNDN0 | F195 | 20 FA F1 | JSR $F1FA | JSR to GETSEC ($F1FA) to set the BAM into memory and find the first available sector following the revised sector #. |
F198 | F0 03 | BEQ $F19D | If no sector is available on this track (Z flag = 1), branch to FNDN2 . | |
FNDN1 | F19A | 4C 90 EF | JMP $EF90 | Exit with a JMP to WUSED ($EF90) to set this new sector as in use. |
FNDN2 | F19D | A9 00 | LDA #$00 | Set the sector number in SECTOR ($81) to $00. |
F19F | 85 81 | STA $81 | ||
F1A1 | 20 FA F1 | JSR $F1FA | JSR to GETSEC ($F1FA) to set the BAM into memory and find the first available sector following the revised sector #. | |
F1A4 | D0 F4 | BNE $F19A | If a sector is available on this track (Z flag = 0), branch to FNDN1. | |
F1A6 | 4C F5 F1 | JMP $F1F5 | JMP to DERR ($F1F5) to abort. | |
Find optimum initial track and sector |
||||
INTTS | F1A9 | A9 01 | LDA #$01 | Load .A with $01, OR it with the write- BAM flag, WBAM ($02F9). and store the result back in WBAM to indicate a write of BAM is pending. |
F1AB | 0D F9 02 | ORA $02F9 | ||
F1AE | 8D F9 02 | STA $02F9 | ||
F1B1 | A5 86 | LDA $86 | Load .A with the value from R0 ($86) and save it onto the stack. | |
F1B3 | 48 | PHA | ||
F1B4 | A9 01 | LDA #$01 | Store $01 into R0 ($86) . NOTE: TRACK = DIRECTORY TRACK - R0 | |
F1B6 | 85 86 | STA $86 | ||
F1B8 | AD 85 FE | LDA $FE85 | Load .A with the directory track number ($12) from DIRTRK ($FE85) . | |
F1BB | 38 | SEC | Set the carry flag, subtract the counter in R0 and store the result into TRACK ($80) . | |
F1BC | E5 86 | SBC $86 | ||
F1BE | 85 80 | STA $80 | ||
F1C0 | 90 09 | BCC $F1CB | If the value in TRACK is less than or equal to 0, branch to ITS2. | |
F1C2 | F0 07 | BEQ $F1CB | ||
Do tracks 17 -> 1 |
||||
F1C4 | 20 11 F0 | JSR $F011 | JSR to SETBAM ($F011) to set the pointer to the BAM. | |
F1C7 | B1 6D | LDA ($6D),Y | Load .A with the number of blocks free on this track from (BMPNT) ,Y; ($6D,Y) . | |
F1C9 | D0 1B | BNE $F1E6 | If some sectors are free on this track (Z flag not set). branch to FNDSEC ($F1E6) . | |
None free on lower track so try a higher one: |
||||
ITS2 | F1CB | AD 85 FE | LDA $FE85 | Load .A with the directory track number ($12) from DIRTRK ($FE85). |
F1CE | 18 | CLC | Clear the carry flag, add the counter in R0 and store the result into TRACK ($80) | |
F1CF | 65 86 | ADC $86 | ||
F1D1 | 85 80 | STA $80 | ||
F1D3 | E6 86 | INC $86 | Increment the track counter in R0 ($86) . | |
F1D5 | CD D7 FE | CMP $FED7 | If the value in TRACK is greater than or equal to the maximum track number (#36), branch to ITS3. | |
F1D8 | 90 05 | BCC $F1DF | ||
F1DA | A9 67 | LDA #$67 | Load .A with $6 7 to indicate a SYSTEM TRACK & SECTOR error and JSR to CMDER2 ($E645) . | |
F1DC | 20 45 E6 | JSR $E645 | ||
ITS3 | F1DF | 20 11 F0 | JSR $F011 | Do tracks 19 -> 35 JSR to SETBAM ($F011) to set the pointer to the BAM. |
F1E2 | B1 6D | LDA ($6D),Y | Load .A with the number of blocks free on this track from (BMPNT) ,Y; ($6D,Y) . | |
F1E4 | F0 D2 | BEQ $F1B8 | If no sectors are free on this track (Z flag is set). branch to ITS1 to try a lower numbered track. | |
FNDSEC | F1E6 | 68 | PLA | Pull the original value of RO off the stack and store it back in RO ($86). |
F1E7 | 85 86 | STA $86 | ||
F1E9 | A9 00 | LDA #$00 | Store $00 as the sector number in SECTOR ($81) . | |
F1EB | 85 81 | STA $81 | ||
F1ED | 20 FA F1 | JSR $F1FA | JSR to GETSEC ($F1FA) to set the BAM and find first available sector. | |
F1F0 | F0 03 | BEQ $F1F5 | If no sector available, branch to DERR. | |
F1F2 | 4C 90 EF | JMP $EF90 | Terminate routine with a JMP to WUSED ($EF90) to mark sector as used in BAM. | |
Error in BAM |
||||
DERR | F1F5 | A9 71 | LDA #$71 | Load .A with $71 to indicate an error in the BAM and JSR to CMDER2 ($E645) . |
F1F7 | 20 45 E6 | JSR $E645 | ||
Set the BAM and find the first available sector starting at SECTOR |
||||
GETSEC | F1FA | 20 11 F0 | JSR $F011 | JSR to SETBAM ($F011) to set the pointer to the BAM. |
F1FD | 98 | TYA | Transfer the .Y value into .A and save it onto the stack. | |
F1FE | 48 | PHA | ||
F1FF | 20 20 F2 | JSR $F220 | JSR to AVCK ($F220) to check the bit map validity. | |
F202 | A5 80 | LDA $80 | Load .A with the current track number from TRACK ($80) and JSR to MAXSEC ($F24B) to find the maximum sector number allowed on this track. On return, store the maximum sector number (in .A) into LSTSEC ($024E) . | |
F204 | 20 4B F2 | JSR $F24B | ||
F207 | 8D 4E 02 | STA $024E | ||
F20A | 68 | PLA | Pull the original .Y value off the stack and store it in TEMP ($6F) . | |
F20B | 85 6F | STA $6F | ||
GS10 | F20D | A5 81 | LDA $81 | Compare the current sector number from SECTOR ($81) with the maximum sector count in LSTSEC ($024E). If the current sector number is too large, branch to GS20. |
F20F | CD 4E 02 | CMP $024E | ||
F212 | B0 09 | BCS $F21D | ||
F214 | 20 D5 EF | JSR $EFD5 | JSR to FREUS3 ($EFD5) to calculate index into the BAM. On return, if the Z flag is not set, the sector is free so branch to GS30. | |
F217 | D0 06 | BNE $F21F | ||
Sector was not free |
||||
F219 | E6 81 | INC $81 | Increment the sector number in SECTOR ($81) and branch (always) to GS10. | |
F21B | D0 F0 | BNE $F20D | ||
GS20 | F21D | A9 00 | LDA #$00 | Load .A with $00. Note that this sets the Z flag to indicate that a free sector was not found. |
GS30 | F21F | 60 | RTS | Terminate routine with an RTS. |
Check the validity of the bit map |
||||
AVCK | F220 | A5 6F | LDA $6F | Load .A with the value of TEMP ($6F) and save it onto the stack. |
F222 | 48 | PHA | ||
F223 | A9 00 | LDA #$00 | Store $00 into TEMP ($6F) . | |
F225 | 85 6F | STA $6F | ||
F227 | AC 86 FE | LDY $FE86 | Load .Y with $04, the number of bytes per track in the BAM from BAMSIZ ($FE86) | |
F22A | 88 | DEY | Decrement .Y by 1 (now $03) . | |
AC10 | F22B | A2 07 | LDX #$07 | Load .X with $07 (bit counter). |
AC20 | F22D | B1 6D | LDA ($6D),Y | Load .A with the BAM byte for this track from (BMPNT) ,Y; ($6D,Y). and AND the BAM byte with the bit mask from BMASK,X ($EFE9,X) to isolate the bit for this sector. If the result is $00, the sector is allocated so branch to AC30. |
F22F | 3D E9 EF | AND $EFE9,X | ||
F232 | F0 02 | BEQ $F236 | ||
F234 | E6 6F | INC $6F | Since the sector is free, increment the count of free sectors in TEMP ($6F) . | |
AC30 | F236 | CA | DEX | Decrement the bit counter (1 bit/sector) in .X. If the count is greater than or equal to $00, branch to AC20. |
F237 | 10 F4 | BPL $F22D | ||
F239 | 88 | DEY | Decrement the byte counter (8 sectors/ byte) in .Y. If the count is not $00, branch to AGIO. | |
F23A | D0 EF | BNE $F22B | ||
F23C | B1 6D | LDA ($6D),Y | Compare the number of bytes free on the track as given in the BAM at (BMPNT) ,Y ($6D,Y) with the count we did in TEMP ($6F). If the counts DO NOT MATCH, branch to AC40 to abort. | |
F23E | C5 6F | CMP $6F | ||
F240 | D0 04 | BNE $F246 | ||
F242 | 68 | PLA | Pull the original value of TEMP off the stack and restore it into TEMP ($6F) . | |
F243 | 85 6F | STA $6F | ||
F245 | 60 | RTS | Terminate routine with an RTS. | |
Error in BAM |
||||
AC40 | F246 | A9 71 | LDA #$71 | Load .A with $71 to indicate an error in the BAM and JSR to CMDER2 ($E645) . |
F248 | 20 45 E6 | JSR $E645 | ||
MAXSEC | F24B | AE D6 FE | LDX $FED6 | Returns the number of sectors allowed on this track. Track number in .A. Load .X with the number of zones ($04) from NZONES ($FED6) . |
MAX1 | F24E | DD D6 FE | CMP $FED6,X | Compare the track number (in .A) with the zone boundary value from TRKNUM-1,X ($FED6,X) . |
F251 | CA | DEX | Decrement the zone count in .X. | |
F252 | B0 FA | BCS $F24E | If the track number in .A is less than the boundary value, branch to MAX1. | |
F254 | BD D1 FE | LDA $FED1,X | Load .A with the number of sectors/track for this zone from NUMSEC,X ($FED1,X). | |
F257 | 60 | RTS | Terminate routine with an RTS. | |
Kill protection: Does NOTHING on 1541! |
||||
KILLP | F258 | 60 | RTS | Terminate routine with an RTS. |
Disk contoller routines |
||||
CNTINT | F259 | A9 6F | LDA #$6F | Controller initialization |
F25B | 8D 02 1C | STA $1C02 | Store %01101111 in DDRB2 ($1C02) to set the data direction for Port B. | |
F25E | 29 F0 | AND #$F0 | Store %01100000 in DSKCNT ($1C00) to turn off the motor & LED and set phase A | |
F260 | 8D 00 1C | STA $1C00 | ||
F263 | AD 0C 1C | LDA $1C0C | ||
F266 | 29 FE | AND #$FE | ||
F268 | 09 0E | ORA #$0E | ||
F26A | 09 E0 | ORA #$E0 | ||
F26C | 8D 0C 1C | STA $1C0C | Set the peripheral control register ($1C0C) for neg edge latch mode, CA2 hi to disable the SO line to the 6502, CB1 is input, and CB2 is R/W mode control. | |
F26F | A9 41 | LDA #$41 | ||
F271 | 8D 0B 1C | STA $1C0B | ||
F274 | A9 00 | LDA #$00 | ||
F276 | 8D 06 1C | STA $1C06 | ||
F279 | A9 3A | LDA #$3A | ||
F27B | 8D 07 1C | STA $1C07 | Set T1HL2 ($1C07) to $3A and T1LL2 ( $1C06 ) to $00 so there is 20ms between IRQ's | |
F27E | 8D 05 1C | STA $1C05 | ||
F281 | A9 7F | LDA #$7F | Store $7F in IER2 ($1C0E) to clear all IRQ sources. | |
F283 | 8D 0E 1C | STA $1C0E | ||
F286 | A9 C0 | LDA #$C0 | Store $C0 in IFR2 ($1C0D) to clear the bit and then into IER2 ($1C0E) to enable the timer IRQ. | |
F288 | 8D 0D 1C | STA $1C0D | ||
F28B | 8D 0E 1C | STA $1C0E | ||
F28E | A9 FF | LDA #$FF | Store $FF as the current drive, CDRIVE ($3E) and as init flag, FTNUM ($51). | |
F290 | 85 3E | STA $3E | ||
F292 | 85 51 | STA $51 | ||
F294 | A9 08 | LDA #$08 | Set header block ID, HBID ($39) to $08 | |
F296 | 85 39 | STA $39 | ||
F298 | A9 07 | LDA #$07 | Set data block ID, DBID ($47) to $07 | |
F29A | 85 47 | STA $47 | ||
F29C | A9 05 | LDA #$05 | Set NXTST ($62/3) to point to INACT ($FA05) . | |
F29E | 85 62 | STA $62 | ||
F2A0 | A9 FA | LDA #$FA | ||
F2A2 | 85 63 | STA $63 | ||
F2A4 | A9 C8 | LDA #$C8 | Set MINSTP ($64) to 200 to indicate the minimum number of steps required to invoke the fast stepping mode. | |
F2A6 | 85 64 | STA $64 | ||
F2A8 | A9 04 | LDA #$04 | Store 4 into AS ($5E) to indicate the number of steps needed to accelerate and decelerate the head. | |
F2AA | 85 5E | STA $5E | ||
F2AC | A9 04 | LDA #$04 | Store 4 into AF ($5F) as the acceleration/ deceleration factor. | |
F2AE | 85 5F | STA $5F | ||
Main controller loop
|
||||
LCC | F2B0 | BA | TSX | Save stack pointer in SAVSP ($49) . |
F2B1 | 86 49 | STX $49 | ||
F2B3 | AD 04 1C | LDA $1C04 | Reset IRQ flag | |
F2B6 | AD 0C 1C | LDA $1C0C | Set bits 3,2, & 1 of PCR2 ($1C0C) to enable S.O. to 6502, hi output | |
F2B9 | 09 0E | ORA #$0E | ||
F2BB | 8D 0C 1C | STA $1C0C | ||
TOP | F2BE | A0 05 | LDY #$05 | Top of loop to scan job queue. Load .Y with #$05 as pointer to top of queue. |
F2C0 | B9 00 00 | LDA $0000,Y | ||
CONT10 | F2C3 | 10 2E | BPL $F2F3 | Load .A with byte from queue, JOBS,Y ($0000, Y). Test if bit 7 is set. If not, branch to CONT20 since no job here. |
F2C5 | C9 D0 | CMP #$D0 | Check if job is a jump code ($D0) . If not, branch to CONT30. | |
F2C7 | D0 04 | BNE $F2CD | ||
F2C9 | 98 | TYA | ||
F2CA | 4C 70 F3 | JMP $F370 | Transfer queue position from .Y to .A and JMP to EX2 ($F370) to do jump job. | |
CONT30 | F2CD | 29 01 | AND #$01 | AND job code with $01. If result is 0, the drive # is valid so branch to CONT35 |
F2CF | F0 07 | BEQ $F2D8 | ||
F2D1 | 84 3F | STY $3F | Load .A with $0F to indicate a bad drive number and JMP to ERRR ($F969) | |
F2D3 | A9 0F | LDA #$0F | ||
F2D5 | 4C 69 F9 | JMP $F969 | ||
CONT35 | F2D8 | AA | TAX | Store job drive # in DRIVE ($3D) . |
F2D9 | 85 3D | STA $3D | ||
F2DB | C5 3E | CMP $3E | Compare job drive # with current drive number in CDRIVE ($3E). (CDRIVE is $FF if the drive is not turned on.) If they are equal, branch to CONT40 | |
F2DD | F0 0A | BEQ $F2E9 | ||
F2DF | 20 7E F9 | JSR $F97E | JSR to TURNON ($F97E) to turn on drive. | |
F2E2 | A5 3D | LDA $3D | Set CDRIVE to job drive # and exit for now with a JMP to END ($F99C). | |
F2E4 | 85 3E | STA $3E | ||
F2E6 | 4C 9C F9 | JMP $F99C | ||
CONT40 | F2E9 | A5 20 | LDA $20 | Check the value in DRVST ($20) to see if the drive is up to speed. If bit 7 is set, it isn't so JMP to END ($F99C). |
F2EB | 30 03 | BMI $F2F0 | ||
F2ED | 0A | ASL | Check if the head is stepping. If it is, exit with a JMP to END ($F99C). If it is not stepping, branch to QUE. | |
F2EE | 10 09 | BPL $F2F9 | ||
F2F0 | 4C 9C F9 | JMP $F99C | ||
CONT20 | F2F3 | 88 | DEY | Decrement .Y pointer into queue. If more locations in queue, branch back to CONT10. If none left JMP to END ($F99C). |
F2F4 | 10 CA | BPL $F2C0 | ||
F2F6 | 4C 9C F9 | JMP $F99C | ||
QUE | F2F9 | A9 20 | LDA #$20 | Store $20 in DRVST ($20) to set drive status to running. |
F2FB | 85 20 | STA $20 | ||
F2FD | A0 05 | LDY #$05 | Check if head needs to be stepped for this job. If not, branch to QUE20. | |
F2FF | 84 3F | STY $3F | ||
F301 | 20 93 F3 | JSR $F393 | ||
F304 | 30 1A | BMI $F320 | ||
QUE05 | F306 | C6 3F | DEC $3F | Check other jobs to see if one for this track. If not, calculate steps needed. |
F308 | 10 F7 | BPL $F301 | ||
F30A | A4 41 | LDY $41 | ||
F30C | 20 95 F3 | JSR $F395 | ||
F30F | A5 42 | LDA $42 | ||
F311 | 85 4A | STA $4A | ||
F313 | 06 4A | ASL $4A | ||
F315 | A9 60 | LDA #$60 | Store $60 in DRVST ($20) to set drive status to stepping, store destination track in DRVTRK ($22) and exit for now with a JMP to END ($F99C) . | |
F317 | 85 20 | STA $20 | ||
F319 | B1 32 | LDA ($32),Y | ||
F31B | 85 22 | STA $22 | ||
F31D | 4C 9C F9 | JMP $F99C | ||
QUE20 | F320 | 29 01 | AND #$01 | Check if job is on current drive. If not, branch back to QUE05. |
F322 | C5 3D | CMP $3D | ||
F324 | D0 E0 | BNE $F306 | ||
F326 | A5 22 | LDA $22 | ||
F328 | F0 12 | BEQ $F33C | ||
F32A | 38 | SEC | Calculate distance to track | |
F32B | F1 32 | SBC ($32),Y | ||
F32D | F0 0D | BEQ $F33C | Are we on track already? if so, branch to GOTU. | |
F32F | 49 FF | EOR #$FF | Store number of steps to the desired track in NXTRK ($42) | |
F331 | 85 42 | STA $42 | ||
F333 | E6 42 | INC $42 | ||
F335 | A5 3F | LDA $3F | ||
F337 | 85 41 | STA $41 | ||
F339 | 4C 06 F3 | JMP $F306 | JMP back to QUE05 to check if another job is closer. | |
GOTU | F33C | A2 04 | LDX #$04 | Calculate zone (1-4) of the desired track and store the number of sectors on the track in SECTR ($43). |
F33E | B1 32 | LDA ($32),Y | ||
F340 | 85 40 | STA $40 | ||
F342 | DD D6 FE | CMP $FED6,X | ||
F345 | CA | DEX | ||
F346 | B0 FA | BCS $F342 | ||
F348 | BD D1 FE | LDA $FED1,X | ||
F34B | 85 43 | STA $43 | ||
F34D | 8A | TXA | Calculate recording density and set the divide by N counter by storing a value in DSKCNT ($1C00) . | |
F34E | 0A | ASL | ||
F34F | 0A | ASL | ||
F350 | 0A | ASL | ||
F351 | 0A | ASL | ||
F352 | 0A | ASL | ||
F353 | 85 44 | STA $44 | ||
F355 | AD 00 1C | LDA $1C00 | ||
F358 | 29 9F | AND #$9F | ||
F35A | 05 44 | ORA $44 | ||
F35C | 8D 00 1C | STA $1C00 | ||
F35F | A6 3D | LDX $3D | Load .x with drive number and .A with the job code. | |
F361 | A5 45 | LDA $45 | ||
F363 | C9 40 | CMP #$40 | Compare job code with $40. If equal, branch to BMP to do bump job. | |
F365 | F0 15 | BEQ $F37C | ||
EXE | F367 | C9 60 | CMP #$60 | Compare job code with $60. If equal, branch to EX to do execute job. |
F369 | F0 03 | BEQ $F36E | ||
F36B | 4C B1 F3 | JMP $F3B1 | Not Bump or Execute, JMP to SEAK ($F3B1) | |
F36E | A5 3F | LDA $3F | ||
F370 | 18 | CLC | ||
F371 | 69 03 | ADC #$03 | ||
F373 | 85 31 | STA $31 | ||
F375 | A9 00 | LDA #$00 | ||
Do an execute job |
||||
EX | F377 | 85 30 | STA $30 | Set pointer to buffer in BUFPNT ($30/1) |
F379 | 6C 30 00 | JMP ($0030) | Do indirect JMP via BUFPNT to the code that starts at the start of the buffer. Do a bump to track #1 | |
BMP | F37C | A9 60 | LDA #$60 | Store $60 as the drive status, DRVST (20) to indicate head is stepping. |
F37E | 85 20 | STA $20 | ||
F380 | AD 00 1C | LDA $1C00 | Set track phase to phase A | |
F383 | 29 FC | AND #$FC | ||
F385 | 8D 00 1C | STA $1C00 | ||
F388 | A9 A4 | LDA #$A4 | Store -45 ($A4) as the number of tracks to move head in STEPS ($4A) . | |
F38A | 85 4A | STA $4A | ||
F38C | A9 01 | LDA #$01 | Set DRVTRK ($22) to 1 as new track# | |
F38E | 85 22 | STA $22 | ||
F390 | 4C 69 F9 | JMP $F969 | Job done so JMP to ERRR ($F969). | |
SETJB | F393 | A4 3F | LDY $3F | Sub to set pointer to buffer, BUFPNT ($30/31) and into header table, HDRPNT ($32) for this position in job queue. |
F395 | B9 00 00 | LDA $0000,Y | ||
F398 | 48 | PHA | ||
F399 | 10 10 | BPL $F3AB | ||
F39B | 29 78 | AND #$78 | ||
F39D | 85 45 | STA $45 | ||
F39F | 98 | TYA | ||
F3A0 | 0A | ASL | ||
F3A1 | 69 06 | ADC #$06 | ||
F3A3 | 85 32 | STA $32 | ||
F3A5 | 98 | TYA | ||
F3A6 | 18 | CLC | ||
F3A7 | 69 03 | ADC #$03 | ||
F3A9 | 85 31 | STA $31 | ||
F3AB | A0 00 | LDY #$00 | ||
F3AD | 84 30 | STY $30 | ||
F3AF | 68 | PLA | ||
F3B0 | 60 | RTS | ||
Search for a valid header block on this trackUp to 90 header and data blocks are scanned while looking for a valid header block before this routine gives up. A valid header block must have:
|
||||
SEAK | F3B1 | A2 5A | LDX #$5A | Store $5A (90) in TMP ($4B) as the sync mark counter (quit if counts down to 0) |
F3B3 | 86 4B | STX $4B | ||
F3B5 | A2 00 | LDX #$00 | ||
F3B7 | A9 52 | LDA #$52 | Store $52 into STAB ($24) as the header block ID code to wait for (GCR for $08). | |
F3B9 | 85 24 | STA $24 | ||
F3BB | 20 56 F5 | JSR $F556 | JSR to SYNC ($F556) to wait for sync | |
F3BE | 50 FE | BVC $F3BE | Read first character after sync | |
F3C0 | B8 | CLV | ||
F3C1 | AD 01 1C | LDA $1C01 | ||
F3C4 | C5 24 | CMP $24 | Compare it to character in STAB ($24) | |
F3C6 | D0 3F | BNE $F407 | If no match, this is not a header block so branch to SEEK20. | |
SEEK15 | F3C8 | 50 FE | BVC $F3C8 | Loop to read in the next 7 characters and store in STAB+1,X ($25, X). |
F3CA | B8 | CLV | ||
F3CB | AD 01 1C | LDA $1C01 | ||
F3CE | 95 25 | STA $25,X | ||
F3D0 | E8 | INX | ||
F3D1 | E0 07 | CPX #$07 | ||
F3D3 | D0 F3 | BNE $F3C8 | ||
F3D5 | 20 97 F4 | JSR $F497 | JSR to CNVBIN ($F497) to convert the header bytes from GCR form to normal. | |
SEEK30 | F3D8 | A0 04 | LDY #$04 | Loop to compute checksum of header read EOR checksum, sector, track, ID1 & ID2. |
F3DA | A9 00 | LDA #$00 | ||
F3DC | 59 16 00 | EOR $0016,Y | ||
F3DF | 88 | DEY | ||
F3E0 | 10 FA | BPL $F3DC | ||
F3E2 | C9 00 | CMP #$00 | If computed checksum is not 0, branch to CSERR ($F41E) to report error. | |
F3E4 | D0 38 | BNE $F41E | ||
F3E6 | A6 3E | LDX $3E | Update current track from header data | |
F3E8 | A5 18 | LDA $18 | ||
F3EA | 95 22 | STA $22,X | ||
F3EC | A5 45 | LDA $45 | Compare job code in JOB ($45) with $30 to see if it is a seek job. If it is, branch to ESEEK ($F410) to do it. | |
F3EE | C9 30 | CMP #$30 | ||
F3F0 | F0 1E | BEQ $F410 | ||
F3F2 | A5 3E | LDA $3E | Compare master disk ID in $12/13 to the disk ID from the header in $16/17. If they don't match, branch to BADID ($F41B) to report a disk ID mismatch error. | |
F3F4 | 0A | ASL | ||
F3F5 | A8 | TAY | ||
F3F6 | B9 12 00 | LDA $0012,Y | ||
F3F9 | C5 16 | CMP $16 | ||
F3FB | D0 1E | BNE $F41B | ||
F3FD | B9 13 00 | LDA $0013,Y | ||
F400 | C5 17 | CMP $17 | ||
F402 | D0 17 | BNE $F41B | ||
F404 | 4C 23 F4 | JMP $F423 | JMP to WSWCT ($F423) to find the best- sector on this track to service (usually the current sector + 2) | |
SEEK20 | F407 | C6 4B | DEC $4B | Decrement SYNC counter in TMP($4B) by 1 to see if we should check more syncs. If not yet, branch back to SEEK10. If 0, load .A with a $02 (to indicate header block not found) and JMP to ERRR ($F969) |
F409 | D0 B0 | BNE $F3BB | ||
F40B | A9 02 | LDA #$02 | ||
F40D | 20 69 F9 | JSR $F969 | ||
ESEEK | F410 | A5 16 | LDA $16 | Change master disk ID in $12/$13 to match the ID read in from $16/17 |
F412 | 85 12 | STA $12 | ||
F414 | A5 17 | LDA $17 | ||
F416 | 85 13 | STA $13 | ||
DONE | F418 | A9 01 | LDA #$01 | Load .A with a $01 (to indicate job completed OK) and exit to error handler |
F41A | 2C | BYTE $2C to skip next instruction | ||
BADID | F41B | A9 0B | LDA #$0B | Load .A with a $0B (to indicate disk ID mismatch) and exit to error handler |
F41D | 2C | BYTE $2C to skip next instruction | ||
CSERR | F41E | A9 09 | LDA #$09 | Load .A with a $09 (to indicate a bad checksum) and exit to error handler |
F420 | 4C 69 F9 | JMP $F969 | ||
WSECT | F423 | A9 7F | LDA #$7F | Determine best sector on this track to service (optimum is current sector + 2) Store $7F as the current sector in $4C |
F425 | 85 4C | STA $4C | ||
F427 | A5 19 | LDA $19 | Load .A with the sector number from the header just read from HEADER+3 ($19). | |
F429 | 18 | CLC | Add 2 | |
F42A | 69 02 | ADC #$02 | ||
F42C | C5 43 | CMP $43 | Compare sum to the number of sectors on this track in SECTR ($43). If sum is too big, subtract the number of sectors. | |
F42E | 90 02 | BCC $F432 | ||
F430 | E5 43 | SBC $43 | ||
L460 | F432 | 85 4D | STA $4D | Store sum as next sector to be serviced in NEXTS ($4D) . |
F434 | A2 05 | LDX #$05 | ||
F436 | 86 3F | STX $3F | ||
F438 | A2 FF | LDX #$FF | ||
L480 | F43A | 20 93 F3 | JSR $F393 | JSR to SETJB ($F393) to set pointers. |
F43D | 10 44 | BPL $F483 | ||
F43F | 85 44 | STA $44 | ||
F441 | 29 01 | AND #$01 | ||
F443 | C5 3E | CMP $3E | Check to be sure job is for this drive. If not, branch to L470 ($F483). | |
F445 | D0 3C | BNE $F483 | ||
F447 | A0 00 | LDY #$00 | Check to be sure job is for this track. If not, branch to L470 ($F483). | |
F449 | B1 32 | LDA ($32),Y | ||
F44B | C5 40 | CMP $40 | ||
F44D | D0 34 | BNE $F483 | ||
F44F | A5 45 | LDA $45 | Compare job code in JOB ($45) with $60 to see if it is an execute job. If it- is, branch to L465. | |
F451 | C9 60 | CMP #$60 | ||
F453 | F0 0C | BEQ $F461 | ||
F455 | A0 01 | LDY #$01 | Load .A with job's sector, (HDRPNT) ,Y and subtract the upcoming sector from NEXTS ($4D). If result is positive, branch to L465 since sector coming up. | |
F457 | 38 | SEC | ||
F458 | B1 32 | LDA ($32),Y | ||
F45A | E5 4D | SBC $4D | ||
F45C | 10 03 | BPL $F461 | ||
F45E | 18 | CLC | Add value from NEXTS ($4D) back in. | |
F45F | 65 43 | ADC $43 | ||
L465 | F461 | C5 4C | CMP $4C | Compare to distance to other sector request. If further away, branch to L470 since other job is closer. |
F463 | B0 1E | BCS $F483 | ||
F465 | 48 | PHA | Save distance to sector on the stack. Check job code in JOB ($45). If a read job, branch to TSTRDJ. | |
F466 | A5 45 | LDA $45 | ||
F468 | F0 14 | BEQ $F47E | ||
F46A | 68 | PLA | This is a write job. Pull distance to sector off the stack. Since a write job requires set up time, if sector is less than 9 ahead or more than 12 ahead, we are better off doing another job so branch to L470. | |
F46B | C9 09 | CMP #$09 | ||
F46D | 90 14 | BCC $F483 | ||
F46F | C9 0C | CMP #$0C | ||
F471 | B0 10 | BCS $F483 | ||
DOITT | F473 | 85 4C | STA $4C | This job is closer than others so set up by storing distance in CSECT ($4C) and setting BUFPNT to point to the buffer. Branch always to L470 |
F475 | A5 3F | LDA $3F | ||
F477 | AA | TAX | ||
F478 | 69 03 | ADC #$03 | ||
F47A | 85 31 | STA $31 | ||
F47C | D0 05 | BNE $F483 | ||
TSTRDJ | F47E | 68 | PLA | This is a read job. Pull distance to sector off the stack. Since a read job doesn't need much set up time, if sector is less than 6 ahead, we better do it so branch to DOITT. |
F47F | C9 06 | CMP #$06 | ||
F481 | 90 F0 | BCC $F473 | ||
L470 | F483 | C6 3F | DEC $3F | Decrement queue position in JOBN ($3F) by 1. If more to check branch to L480. |
F485 | 10 B3 | BPL $F43A | ||
F487 | 8A | TXA | No more to check. Test if any jobs were found. If none, JMP to END ($F99C). If yes, set up job and JMP to REED ($F4CA) | |
F488 | 10 03 | BPL $F48D | ||
F48A | 4C 9C F9 | JMP $F99C | ||
F48D | 86 3F | STX $3F | ||
F48F | 20 93 F3 | JSR $F393 | ||
F492 | A5 45 | LDA $45 | ||
F494 | 4C CA F4 | JMP $F4CA | ||
CNVRTN | F497 | A5 30 | LDA $30 | Convert GCR image of header into the normal 8 bit binary and move the values into $16/7/8/9/A. The characters decoded include: -Header block ID code (usually $08) -Hdr block checksum (EOR of T/S/ID1/ID2) -Sector number -Track number -ID2 (2nd ID chr given when formatted) -ID1 (1st ID chr given when formatted) -The remaining characters are junk! |
F499 | 48 | PHA | ||
F49A | A5 31 | LDA $31 | ||
F49C | 48 | PHA | ||
F49D | A9 24 | LDA #$24 | ||
F49F | 85 30 | STA $30 | ||
F4A1 | A9 00 | LDA #$00 | ||
F4A3 | 85 31 | STA $31 | ||
F4A5 | A9 00 | LDA #$00 | ||
F4A7 | 85 34 | STA $34 | ||
F4A9 | 20 E6 F7 | JSR $F7E6 | ||
F4AC | A5 55 | LDA $55 | ||
F4AE | 85 18 | STA $18 | ||
F4B0 | A5 54 | LDA $54 | ||
F4B2 | 85 19 | STA $19 | ||
F4B4 | A5 53 | LDA $53 | ||
F4B6 | 85 1A | STA $1A | ||
F4B8 | 20 E6 F7 | JSR $F7E6 | ||
F4BB | A5 52 | LDA $52 | ||
F4BD | 85 17 | STA $17 | ||
F4BF | A5 53 | LDA $53 | ||
F4C1 | 85 16 | STA $16 | ||
F4C3 | 68 | PLA | ||
F4C4 | 85 31 | STA $31 | ||
F4C6 | 68 | PLA | ||
F4C7 | 85 30 | STA $30 | ||
F4C9 | 60 | RTS | ||
Read in the track and sector that is specified in the header table |
||||
READ | F4CA | C9 00 | CMP #$00 | Check if this is a read job. If not, JMP to WRIGHT ($F4CE) |
F4CC | F0 03 | BEQ $F4D1 | ||
F4CE | 4C 6E F5 | JMP $F56E | ||
READ01 | F4D1 | 20 0A F5 | JSR $F50A | JSR to DSTRT ($F50A) find header and set up to the start of the data block |
READ11 | F4D4 | 50 FE | BVC $F4D4 | Loop to read first 256 data bytes and store them in the data buffer . |
F4D6 | B8 | CLV | ||
F4D7 | AD 01 1C | LDA $1C01 | ||
F4DA | 91 30 | STA ($30),Y | ||
F4DC | C8 | INY | ||
F4DD | D0 F5 | BNE $F4D4 | ||
READ20 | F4DF | A0 BA | LDY #$BA | Loop to read the last 7 data bytes and store them in the overflow buffer from $01BA to $01FF. |
F4E1 | 50 FE | BVC $F4E1 | ||
F4E3 | B8 | CLV | ||
F4E4 | AD 01 1C | LDA $1C01 | ||
F4E7 | 99 00 01 | STA $0100,Y | ||
F4EA | C8 | INY | ||
F4EB | D0 F4 | BNE $F4E1 | ||
F4ED | 20 E0 F8 | JSR $F8E0 | JSR to GCRBIN ($F8E0) to convert the 326 GCR data bytes into 256 normal bytes | |
F4F0 | A5 38 | LDA $38 | Compare the first byte in the data block from BID ($38) with the header block ID character (normally $07) in HDIB ($47) to check if this is a legal data block. | |
F4F2 | C5 47 | CMP $47 | ||
F4F4 | F0 05 | BEQ $F4FB | If they match, branch to READ28. | |
F4F6 | A9 04 | LDA #$04 | No match, so load .A with a 4 to flag a DATA BLOCK NOT FOUND error and JMP to ERRR ($F969). | |
F4F8 | 4C 69 F9 | JMP $F969 | ||
READ28 | F4FB | 20 E9 F5 | JSR $F5E9 | JSR to CHKBLK ($F5E9) to compute the checksum for the data block by EORing all the 256 data bytes. |
F4FE | C5 3A | CMP $3A | Compare the computed checksum in .A with with the checksum read from the disk in CHKSUM ($3A). If equal, branch to READ40 | |
F500 | F0 03 | BEQ $F505 | ||
F502 | A9 05 | LDA #$05 | No match, so load .A with a 5 to flag a DATA BLOCK CHECKSUM error | |
F504 | 2C | Byte $2C to skip over next LDA | ||
F505 | A9 01 | LDA #$01 | Load .A with a 1 to indicate a good read | |
F507 | 4C 69 F9 | JMP $F969 | JMP to ERRR ($F969) | |
DSTRT | F50A | 20 10 F5 | JSR $F510 | JSR to SRCH ($F510) to find the desired header block. JMP to SYNC ($F556) to wait for the data block sync character . |
F50D | 4C 56 F5 | JMP $F556 | ||
SRCH | F510 | A5 3D | LDA $3D | Find a specific header. The track and sector desired must be stored in the header table Use values from the header table and the master disk ID ($12/3) to set up an image of the desired header $16-$19 |
F512 | 0A | ASL | ||
F513 | AA | TAX | ||
F514 | B5 12 | LDA $12,X | ||
F516 | 85 16 | STA $16 | ||
F518 | B5 13 | LDA $13,X | ||
F51A | 85 17 | STA $17 | ||
F51C | A0 00 | LDY #$00 | ||
F51E | B1 32 | LDA ($32),Y | ||
F520 | 85 18 | STA $18 | ||
F522 | C8 | INY | ||
F523 | B1 32 | LDA ($32),Y | ||
F525 | 85 19 | STA $19 | ||
F527 | A9 00 | LDA #$00 | ||
F529 | 45 16 | EOR $16 | EOR the track, sector, and ID characters to calculate the header checksum and store it in $1A. | |
F52B | 45 17 | EOR $17 | ||
F52D | 45 18 | EOR $18 | ||
F52F | 45 19 | EOR $19 | ||
F531 | 85 1A | STA $1A | ||
F533 | 20 34 F9 | JSR $F934 | JSR to CONHDR ($F934) to convert the header image into its GCR image. | |
F536 | A2 5A | LDX #$5A | Load .X with $5A as a counter of the number of sync marks checked. | |
SRCH20 | F538 | 20 56 F5 | JSR $F556 | JSR to SYNC ($F556) to wait for the next sync mark. |
F53B | A0 00 | LDY #$00 | ||
SRCH25 | F53D | 50 FE | BVC $F53D | Loop to scan the 8 bytes following the sync mark to attempt to find a match to the GCR image of the desired header. If any character does not match the image, branch to SRCH30. |
F53F | B8 | CLV | ||
F540 | AD 01 1C | LDA $1C01 | ||
F543 | D9 24 00 | CMP $0024,Y | ||
F546 | D0 06 | BNE $F54E | ||
F548 | C8 | INY | ||
F549 | C0 08 | CPY #$08 | ||
F54B | D0 F0 | BNE $F53D | ||
F54D | 60 | RTS | All characters match so exit with an RTS | |
SRCH30 | F54E | CA | DEX | Decrement, the sync mark counter in .X If counter is not yet, branch back to SRCH20 to wait for next sync. |
F54F | D0 E7 | BNE $F538 | ||
F551 | A9 02 | LDA #$02 | No match, so load .A with a 2 to flag a BLOCK HEADER NOT FOUND error. | |
ERR | F553 | 4C 69 F9 | JMP $F969 | JMP to ERRR ($F969) . |
Wait for SYNC markA SYNC mark is 10 or more consecutive l's bits written onto the disk. It is used to identify the start of a block of information recorded on disk. The first character following a SYNC mark is used to determine whether this is a header block ($08) or a data block ($07). |
||||
SYNC | F556 | A9 D0 | LDA #$D0 | Store $D0 in TIMER1 ($1805) to allow a maximum wait of 20 milliseconds for a sync before timing out. |
F558 | 8D 05 18 | STA $1805 | ||
F55B | A9 03 | LDA #$03 | Load .A with $03 (the error code for a NO SYNC FOUND error) | |
SYNC10 | F55D | 2C 05 18 | BIT $1805 | Test bit 7 of TIMER1 ($1805) to check for a time-out. If time is up, branch to ERR ($F553) to exit. |
F560 | 10 F1 | BPL $F553 | ||
F562 | 2C 00 1C | BIT $1C00 | Test bit 7 of DSKCNT ($1C00) to check for a sync. If no sync, branch back to SYNC 10 to wait some more. | |
F565 | 30 F6 | BMI $F55D | ||
F567 | AD 01 1C | LDA $1C01 | Load .A from DATA2 to reset the PA latch clear the 6502' s overflow flag, and RTS | |
F56A | B8 | CLV | ||
F56B | A0 00 | LDY #$00 | ||
F56D | 60 | RTS | ||
Write contents of data buffer to disk |
||||
WRIGHT | F56E | C9 10 | CMP #$10 | Compare job code in .A with $10 to check if this is write job. If not, JMP to VERIFY ($F691) . |
F570 | F0 03 | BEQ $F575 | ||
F572 | 4C 91 F6 | JMP $F691 | ||
F575 | 20 E9 F5 | JSR $F5E9 | JSR to CHKBLK ($F5E9) to compute the checksum for the data block. Store the checksum in CHKSUM ($3A) . | |
F578 | 85 3A | STA $3A | ||
F57A | AD 00 1C | LDA $1C00 | Load .A from DSKCNT and AND it with $10 to check for write protect tab. If the result is not $00, OK to write so branch to WRT10. Load .A with $08 to flag a WRITE PROTECT error and JMP to ERRR ($F969) | |
F57D | 29 10 | AND #$10 | ||
F57F | D0 05 | BNE $F586 | ||
F581 | A9 08 | LDA #$08 | ||
F583 | 4C 69 F9 | JMP $F969 | ||
WRT10 | F586 | 20 8F F7 | JSR $F78F | JSR to BINGCR ($F78F) to convert data in the buffer into GCR form. |
F589 | 20 10 F5 | JSR $F510 | JSR to SRCH ($F510) to find the correct- header block | |
F58C | A2 08 | LDX #$08 | Wait for 8 more bytes to go by. This is the header gap. NOTE: The header gap on the 1541 is 8 bytes long. The gap on the 4040 is 9 bytes long. This is the main reason why the drives are write incompatible! | |
F58E | 50 FE | BVC $F58E | ||
F590 | B8 | CLV | ||
F591 | CA | DEX | ||
F592 | D0 FA | BNE $F58E | ||
F594 | A9 FF | LDA #$FF | Store $FF in DDRA2 ($1C03) to make Port A an output port- | |
F596 | 8D 03 1C | STA $1C03 | ||
F599 | AD 0C 1C | LDA $1C0C | Load .A from PCR2 ($1C0C). AND the value with $1F, OR it with $C0, and store the result in PCR2 to turn on write mode. | |
F59C | 29 1F | AND #$1F | ||
F59E | 09 C0 | ORA #$C0 | ||
F5A0 | 8D 0C 1C | STA $1C0C | ||
F5A3 | A9 FF | LDA #$FF | Store $FF in DATA2 ($1C01) as the SYNC mark character | |
F5A5 | A2 05 | LDX #$05 | ||
F5A7 | 8D 01 1C | STA $1C01 | ||
F5AA | B8 | CLV | ||
WRTSNC | F5AB | 50 FE | BVC $F5AB | Loop to write out 5 consecutive $FF bytes (5x8 =40 1's) . |
F5AD | B8 | CLV | ||
F5AE | CA | DEX | ||
F5AF | D0 FA | BNE $F5AB | ||
F5B1 | A0 BB | LDY #$BB | Load .Y with $BB to point into the overflow buffer ($01BB-01FF) . | |
WRT30 | F5B3 | B9 00 01 | LDA $0100,Y | Load .A with byte from overflow buffer, wait till last byte is out, store new byte into DATA2 ($1C01). increment .Y pointer, and if more characters to do, branch back to WRT30. |
F5B6 | 50 FE | BVC $F5B6 | ||
F5B8 | B8 | CLV | ||
F5B9 | 8D 01 1C | STA $1C01 | ||
F5BC | C8 | INY | ||
F5BD | D0 F4 | BNE $F5B3 | ||
WRT40 | F5BF | B1 30 | LDA ($30),Y | Load .A with byte from data buffer, wait till last byte is out, store new byte into DATA2 ($1C01), increment .Y pointer, and if more characters to do, branch back to WRT40. |
F5C1 | 50 FE | BVC $F5C1 | ||
F5C3 | B8 | CLV | ||
F5C4 | 8D 01 1C | STA $1C01 | ||
F5C7 | C8 | INY | ||
F5C8 | D0 F5 | BNE $F5BF | ||
F5CA | 50 FE | BVC $F5CA | Wait for final byte to clear | |
F5CC | AD 0C 1C | LDA $1C0C | Load .A from PCR2 (S1C0C). OR the value with $E0, and store the result back in PCR2 to shift to read mode. | |
F5CF | 09 E0 | ORA #$E0 | ||
F5D1 | 8D 0C 1C | STA $1C0C | ||
F5D4 | A9 00 | LDA #$00 | Store $00 in data direction register DDRA2 to make port A an input port. | |
F5D6 | 8D 03 1C | STA $1C03 | ||
F5D9 | 20 F2 F5 | JSR $F5F2 | JSR to WTOBIN ($F5F2) to convert GCR data in buffer back into its normal 8 bit form to prepare to verify it. | |
F5DC | A4 3F | LDY $3F | Convert the write job number in the job queue into a verify job. | |
F5DE | B9 00 00 | LDA $0000,Y | ||
F5E1 | 49 30 | EOR #$30 | ||
F5E3 | 99 00 00 | STA $0000,Y | ||
F5E6 | 4C B1 F3 | JMP $F3B1 | JMP to SEAK ($F3B1) to scan the queue for the next job. | |
Calculate data block checksum |
||||
CHKBLK | F5E9 | A9 00 | LDA #$00 | EOR the 256 data bytes. Return with the checksum in .A |
F5EB | A8 | TAY | ||
F5EC | 51 30 | EOR ($30),Y | ||
F5EE | C8 | INY | ||
F5EF | D0 FB | BNE $F5EC | ||
F5F1 | 60 | RTS | ||
Convert the 10 bit image of the data to normal 8 bit binary.Since 5 encoded bytes (40 bits) are converted into 4 normal bytes (32 bits), the encoded form of 256 data bytes takes up 320 bytes. At the start of this routine the first 64 encoded bvtes that were read are stored in the overflow buffer ($01BA-FF) and the remaining 256 bytes are in the normal data buffer. At the end of the routine the decoded bytes are stored in the normal data buffer. |
||||
WTOBIN | F5F2 | A9 00 | LDA #$00 | Set up pointers to the buffers |
F5F4 | 85 2E | STA $2E | ||
F5F6 | 85 30 | STA $30 | ||
F5F8 | 85 4F | STA $4F | ||
F5FA | A5 31 | LDA $31 | ||
F5FC | 85 4E | STA $4E | ||
F5FE | A9 01 | LDA #$01 | Do the overflow buffer ($01BA-FF) first. | |
F600 | 85 31 | STA $31 | ||
F602 | 85 2F | STA $2F | ||
F604 | A9 BB | LDA #$BB | Store $BB in GCRPNT ($34) so it points to the first byte in the overflow buffer ($01BB) that is to be processed by the routine GET4GB. | |
F606 | 85 34 | STA $34 | ||
F608 | 85 36 | STA $36 | Store $BB in BYTCNT ($52) so it points to the location where the first decoded data byte is to be stored. | |
F60A | 20 E6 F7 | JSR $F7E6 | JSR to GET4GB ($F7E6) to convert the first five GCR bytes into 4 normal bytes (the data block ID + 3 data bytes). The decoded bytes appear in $52-5 | |
F60D | A5 52 | LDA $52 | Store data block ID chr in BID ($38) . | |
F60F | 85 38 | STA $38 | ||
F611 | A4 36 | LDY $36 | Move decoded data b^tes from $53-$55 to the buffer ($01BB-D). Note that the decoded bytes are put back into the overflow buffer. | |
F613 | A5 53 | LDA $53 | ||
F615 | 91 2E | STA ($2E),Y | ||
F617 | C8 | INY | ||
F618 | A5 54 | LDA $54 | ||
F61A | 91 2E | STA ($2E),Y | ||
F61C | C8 | INY | ||
F61D | A5 55 | LDA $55 | ||
F61F | 91 2E | STA ($2E),Y | ||
F621 | C8 | INY | ||
F622 | 84 36 | STY $36 | ||
WTOB14 | F624 | 20 E6 F7 | JSR $F7E6 | JSR to GET4BG ($F7E6) to convert the next 5 GCR bytes to 4 normal bytes and store them in $52-5. |
F627 | A4 36 | LDY $36 | ||
F629 | A5 52 | LDA $52 | Move decoded data bytes from $53-$55 to the buffer ($01BB-D). Note that the decoded bytes are put back into the overflow buffer. | |
F62B | 91 2E | STA ($2E),Y | ||
F62D | C8 | INY | ||
F62E | A5 53 | LDA $53 | ||
F630 | 91 2E | STA ($2E),Y | ||
F632 | C8 | INY | ||
F633 | F0 0E | BEQ $F643 | ||
F635 | A5 54 | LDA $54 | ||
F637 | 91 2E | STA ($2E),Y | ||
F639 | C8 | INY | ||
F63A | A5 55 | LDA $55 | ||
F63C | 91 2E | STA ($2E),Y | ||
F63E | C8 | INY | ||
F63F | 84 36 | STY $36 | ||
F641 | D0 E1 | BNE $F624 | If more in overflow, branch to WT0B14 | |
WTOB50 | F643 | A5 54 | LDA $54 | Move last two data bytes into buffer |
F645 | 91 30 | STA ($30),Y | ||
F647 | C8 | INY | ||
F648 | A5 55 | LDA $55 | ||
F64A | 91 30 | STA ($30),Y | ||
F64C | C8 | INY | ||
F64D | 84 36 | STY $36 | ||
WTOB53 | F64F | 20 E6 F7 | JSR $F7E6 | Loop to convert the 256 bytes in data buffer. JSR to GET4BG ($F7E6) to convert the next 5 GCR bytes to 4 normal bytes and store them in $52-5. |
F652 | A4 36 | LDY $36 | Move decoded data bytes from $53-$55 tc the data buffer. Note that the decoded bytes are put back in the data buffer. | |
F654 | A5 52 | LDA $52 | ||
F656 | 91 30 | STA ($30),Y | ||
F658 | C8 | INY | ||
F659 | A5 53 | LDA $53 | ||
F65B | 91 30 | STA ($30),Y | ||
F65D | C8 | INY | ||
F65E | A5 54 | LDA $54 | ||
F660 | 91 30 | STA ($30),Y | ||
F662 | C8 | INY | ||
F663 | A5 55 | LDA $55 | ||
F665 | 91 30 | STA ($30),Y | ||
F667 | C8 | INY | ||
F668 | 84 36 | STY $36 | ||
F66A | C0 BB | CPY #$BB | ||
F66C | 90 E1 | BCC $F64F | ||
At this point the data bytes have all been decoded. Some bytes are in the overflow buffer and some are in the lower part of the data buffer. The following routines shift the bytes in the buffer up and then fill the lower part of the buffer with the bytes from the overflow buffer. |
||||
WTOB52 | F66E | A9 45 | LDA #$45 | Move decoded bytes in lower part of the data buffer up into their proper places in the buffer. |
F670 | 85 2E | STA $2E | ||
F672 | A5 31 | LDA $31 | ||
F674 | 85 2F | STA $2F | ||
F676 | A0 BA | LDY #$BA | ||
F678 | B1 30 | LDA ($30),Y | ||
F67A | 91 2E | STA ($2E),Y | ||
F67C | 88 | DEY | ||
F67D | D0 F9 | BNE $F678 | ||
F67F | B1 30 | LDA ($30),Y | ||
F681 | 91 2E | STA ($2E),Y | ||
WTOB57 | F683 | A2 BB | LDX #$BB | Move decoded bytes from the overflow buffer to the bottom of the data buffer. |
F685 | BD 00 01 | LDA $0100,X | ||
F688 | 91 30 | STA ($30),Y | ||
F68A | C8 | INY | ||
F68B | E8 | INX | ||
F68C | D0 F7 | BNE $F685 | ||
F68E | 86 50 | STX $50 | Set GCRFLG ($50) to to indicate that the data in buffer is in normal form. | |
F690 | 60 | RTS | Exit with an RTS. | |
Verify a data blockThis routine converts the data in the data buffer into its 10 bit encoded form (GCR). It then compares the GCR image with what is recorded on the disk. The encoded data is then changed back into normal 8 bit binary form. |
||||
VRFY | F691 | C9 20 | CMP #$20 | Compare job code in .A with $20 to check that this is a verify job. If not, JMP to SECTSK (F6CA) to do a sector seek. |
F693 | F0 03 | BEQ $F698 | ||
F695 | 4C CA F6 | JMP $F6CA | ||
F698 | 20 E9 F5 | JSR $F5E9 | JSR to CHKBLK ($F5E9) to compute the checksum for the data block. Store the checksum in CHKSUM ($3A). | |
F69B | 85 3A | STA $3A | ||
F69D | 20 8F F7 | JSR $F78F | JSR to BINGCR ($F78F) to convert the data to its GCR image. | |
F6A0 | 20 0A F5 | JSR $F50A | JSR to DSTRT ($F50A) to find the right sector and wait for data. | |
VRF15 | F6A3 | A0 BB | LDY #$BB | Loop to read 64 data bytes from disk and compare them to those in the overflow buffer. If any bytes do not match, branch to VRF20 to report error, |
F6A5 | B9 00 01 | LDA $0100,Y | ||
F6A8 | 50 FE | BVC $F6A8 | ||
F6AA | B8 | CLV | ||
F6AB | 4D 01 1C | EOR $1C01 | ||
F6AE | D0 15 | BNE $F6C5 | ||
F6B0 | C8 | INY | ||
F6B1 | D0 F2 | BNE $F6A5 | ||
VRF30 | F6B3 | B1 30 | LDA ($30),Y | Loop to read 254 data bytes from disk and compare them to those in the data buffer. If any bytes do not match, branch to VRF20 to report error. |
F6B5 | 50 FE | BVC $F6B5 | ||
F6B7 | B8 | CLV | ||
F6B8 | 4D 01 1C | EOR $1C01 | ||
F6BB | D0 08 | BNE $F6C5 | ||
F6BD | C8 | INY | ||
F6BE | C0 FD | CPY #$FD | ||
F6C0 | D0 F1 | BNE $F6B3 | ||
F6C2 | 4C 18 F4 | JMP $F418 | All bytes match so JMP to DONE ($F418) | |
VRF20 | F6C5 | A9 07 | LDA #$07 | Bad byte, so load .A with $07 to flag a WRITE-VERIFY error & JMP to ERRR ($F969) |
F6C7 | 4C 69 F9 | JMP $F969 | ||
SECTSK | F6CA | 20 10 F5 | JSR $F510 | JSR to SRCH to do a sector search JMP to DONE ($F418) |
F6CD | 4C 18 F4 | JMP $F418 | ||
Convert binary to GCRThis routine is used to convert 4 normal 8 bit bytes into the 10 bit encoded form used for recording onto disk. Encoding involves breaking up each 8 bit normal byte into two 4-bit nybbles. The 5-bit equivalent for each nybble is found by looking in a table. The 10 bits that result are stored in two consecutive memory locations. When four 8-bit bytes are encoded, the resulting 40 bits are stored like this: Four normal 8 bit bytes stored in $52/3/4/5 AAAABBBB CCCCDDDD EEEEFFFF GGGGHHHH Four 10 bit encoded bytes stored in buffer aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh |
||||
PUT4GB | F6D0 | A9 00 | LDA #$00 | Clear critical areas of the buffer where the encoded bytes are to be stored. GTAB to GTAB+4 ($56-5A) |
F6D2 | 85 57 | STA $57 | ||
F6D4 | 85 5A | STA $5A | ||
F6D6 | A4 34 | LDY $34 | ||
F6D8 | A5 52 | LDA $52 | Load first 8-bit byte ($52). AND it with $F0 (11110000) to mask off the low nybble (AAAA0000), do four LSR's to convert the hi nybble to a low nybble (0000AAAA). look up the corresponding five bit GCR value (OOOaaaaa) in BGTAB BGTAB ($F77F+). do three ASL ' s on it (aaaaaOOO). and store it in the first position in the encoded data area ($56) | |
F6DA | 29 F0 | AND #$F0 | ||
F6DC | 4A | LSR | ||
F6DD | 4A | LSR | ||
F6DE | 4A | LSR | ||
F6DF | 4A | LSR | ||
F6E0 | AA | TAX | ||
F6E1 | BD 7F F7 | LDA $F77F,X | ||
F6E4 | 0A | ASL | ||
F6E5 | 0A | ASL | ||
F6E6 | 0A | ASL | ||
F6E7 | 85 56 | STA $56 | ||
F6E9 | A5 52 | LDA $52 | Load first 8-bit byte ($52), AND it with $0F (00001111) to mask off the high nybble (0000BBBB). find the five bit GCR equivalent (OOObbbbb) in BGTAB ($F77F+) , do two ROR's on it alternated with ROR's on $57 .A= (OOOOCbbb) $57=bb000000. AND the value in .A with $07 (00000111). OR the value in .A with the value in $52 (aaaaaOOO). and store the result (aaaaabbb) in the first position of the GCR data buffer (BUFPNT) ,Y ($30, Y). | |
F6EB | 29 0F | AND #$0F | ||
F6ED | AA | TAX | ||
F6EE | BD 7F F7 | LDA $F77F,X | ||
F6F1 | 6A | ROR | ||
F6F2 | 66 57 | ROR $57 | ||
F6F4 | 6A | ROR | ||
F6F5 | 66 57 | ROR $57 | ||
F6F7 | 29 07 | AND #$07 | ||
F6F9 | 05 56 | ORA $56 | ||
F6FB | 91 30 | STA ($30),Y | ||
F6FD | C8 | INY | ||
F6FE | A5 53 | LDA $53 | Load second 8-bit byte ($53), AND it with $F0 (11110000) to mask off the low nybble (CCCC0000), do four LSR's to convert the hi nybble to a low nybble (0000CCCC). lock up the five bit GCR equivalent (OOOccccc) in BGTAB ($F77F+) , do one ASL on it (OOcccccO). OR it with the contents of $57 (bbOOOOOO). and put the result (bbcccccO) in $57. | |
F700 | 29 F0 | AND #$F0 | ||
F702 | 4A | LSR | ||
F703 | 4A | LSR | ||
F704 | 4A | LSR | ||
F705 | 4A | LSR | ||
F706 | AA | TAX | ||
F707 | BD 7F F7 | LDA $F77F,X | ||
F70A | 0A | ASL | ||
F70B | 05 57 | ORA $57 | ||
F70D | 85 57 | STA $57 | ||
F70F | A5 53 | LDA $53 | Load second 8-bit byte ($53), AND it with $0F (00001111) to mask off the high nybble (0000DDDD). find the five bit GCR equivalent (OOOddddd) in BGTAB ($F77F+) , do four ROL's on it (ddddOOOO C=d) , store it in $58 (ddddOOOO). do one more ROL (dddOOOOd C=d). AND it with $01, OR it with the value in $57 (bbcccccO) and store the result (bbcccccd) into the second byte of the GCR buffer | |
F711 | 29 0F | AND #$0F | ||
F713 | AA | TAX | ||
F714 | BD 7F F7 | LDA $F77F,X | ||
F717 | 2A | ROL | ||
F718 | 2A | ROL | ||
F719 | 2A | ROL | ||
F71A | 2A | ROL | ||
F71B | 85 58 | STA $58 | ||
F71D | 2A | ROL | ||
F71E | 29 01 | AND #$01 | ||
F720 | 05 57 | ORA $57 | ||
F722 | 91 30 | STA ($30),Y | ||
F724 | C8 | INY | ||
F725 | A5 54 | LDA $54 | Load third 8-bit byte ($54). AND it with $F0 (11110000) to mask off the low nybble (EEEE0000). do four LSR's to convert the hi nybble to a low nybble (0000EEEE). look up the five bit GCR equivalent (OOOeeeee) in BGTAB ($F77F+) , do one FOR on it (OOOOeeee C=e). OR it with the contents of $58 (ddddOOOO) , store the result (ddddeeee) in the third byte of the GCR buffer, do another ROR (eC000eee)C=e, AND it with $80(10000000) and store the result (eOOOOOOO) in $59. | |
F727 | 29 F0 | AND #$F0 | ||
F729 | 4A | LSR | ||
F72A | 4A | LSR | ||
F72B | 4A | LSR | ||
F72C | 4A | LSR | ||
F72D | AA | TAX | ||
F72E | BD 7F F7 | LDA $F77F,X | ||
F731 | 18 | CLC | ||
F732 | 6A | ROR | ||
F733 | 05 58 | ORA $58 | ||
F735 | 91 30 | STA ($30),Y | ||
F737 | C8 | INY | ||
F738 | 6A | ROR | ||
F739 | 29 80 | AND #$80 | ||
F73B | 85 59 | STA $59 | ||
F73D | A5 54 | LDA $54 | Load third 8-bit byte ($54). AND it with $0F (00001111) to mask off the high nibble (0000FFFF). find the five bit GCR equivalent (OOOfffff ) in BGTAB ($F77F+) , do two ASL's on it (OfffffOO), AND it with $7C (01111100). OR it with the value in $59 (eOOOOOOO). and store the result (efffffOO) in $59 | |
F73F | 29 0F | AND #$0F | ||
F741 | AA | TAX | ||
F742 | BD 7F F7 | LDA $F77F,X | ||
F745 | 0A | ASL | ||
F746 | 0A | ASL | ||
F747 | 29 7C | AND #$7C | ||
F749 | 05 59 | ORA $59 | ||
F74B | 85 59 | STA $59 | ||
F74D | A5 55 | LDA $55 | Load the fourth 8-bit byte ($55), AND it with $F0 (11110000) to mask off the low nybble (GGGG0000). do four LSR's to convert the hi nybble to a low nybble (0000GGGG). look up the five bit GCR equivalent (OOOggggg) in BGTAB ($F77F+), do three ROR's on .A alternated with ROR's on $5A .A= (0000Ogg) $5A= (gggOOOOO) AND .A with $03 (0000 0011). OR .A with the contents of $59 ( efffffOO). & store result (efffffgg) in the fourth byte of the GCR buffer. | |
F74F | 29 F0 | AND #$F0 | ||
F751 | 4A | LSR | ||
F752 | 4A | LSR | ||
F753 | 4A | LSR | ||
F754 | 4A | LSR | ||
F755 | AA | TAX | ||
F756 | BD 7F F7 | LDA $F77F,X | ||
F759 | 6A | ROR | ||
F75A | 66 5A | ROR $5A | ||
F75C | 6A | ROR | ||
F75D | 66 5A | ROR $5A | ||
F75F | 6A | ROR | ||
F760 | 66 5A | ROR $5A | ||
F762 | 29 03 | AND #$03 | ||
F764 | 05 59 | ORA $59 | ||
F766 | 91 30 | STA ($30),Y | ||
F768 | C8 | INY | ||
F769 | D0 04 | BNE $F76F | ||
F76B | A5 2F | LDA $2F | ||
F76D | 85 31 | STA $31 | ||
F76F | A5 55 | LDA $55 | Load the fourth 8-bit byte ($55). AND it with $0F (00001111) to mask off the high nybble (0000HHHH). find the five bit GCR equivalent (OOOhhhhh) in BGTAB ($F77F+) , OR it with the value in $59 (gggOOOOO) , and store the result (ggghhhhh) in the fifth position of the GCR buffer. | |
F771 | 29 0F | AND #$0F | ||
F773 | AA | TAX | ||
F774 | BD 7F F7 | LDA $F77F,X | ||
F777 | 05 5A | ORA $5A | ||
F779 | 91 30 | STA ($30),Y | ||
F77B | C8 | INY | ||
F77C | 84 34 | STY $34 | ||
F77E | 60 | RTS | ||
BGTAB | F77F | 0A 0B 12 13 0E 0F 16 17 09 19 1A 1B 0D 1D 1E 15 | Table of 5 bit GCR equivalents
Note: 5 bits are used to ensure that not more than 2 consecutive 0's are recorded on disk. | |
Create write image of dataThis routine converts 260 normal 8-bit bytes into their 10-bit equivalents to produce an image for writing to disk. A total of 325 GCR bytes are produced. The original 8-bit bytes are:
Total: 260 8-bit binary bytes The first 69 GCR bytes are stored in the overflow buffer ($10BB-FF). The rest of the GCR bytes are stored in buffer X and replace the original data bytes |
||||
BINGCR | F78F | A9 00 | LDA #$00 | Initialize pointers to buffers |
F791 | 85 30 | STA $30 | ||
F793 | 85 2E | STA $2E | ||
F795 | 85 36 | STA $36 | ||
F797 | A9 BB | LDA #$BB | Set pointer to start of overflow $01bb | |
F799 | 85 34 | STA $34 | ||
F79B | 85 50 | STA $50 | ||
F79D | A5 31 | LDA $31 | ||
F79F | 85 2F | STA $2F | ||
F7A1 | A9 01 | LDA #$01 | ||
F7A3 | 85 31 | STA $31 | ||
F7A5 | A5 47 | LDA $47 | Move data block ID code from DBID ($47) and first 3 data characters into a work area ($52/3/4/5) for input by the PUT4GB routine ($F6D0) | |
F7A7 | 85 52 | STA $52 | ||
F7A9 | A4 36 | LDY $36 | ||
F7AB | B1 2E | LDA ($2E),Y | ||
F7AD | 85 53 | STA $53 | ||
F7AF | C8 | INY | ||
F7B0 | B1 2E | LDA ($2E),Y | ||
F7B2 | 85 54 | STA $54 | ||
F7B4 | C8 | INY | ||
F7B5 | B1 2E | LDA ($2E),Y | ||
F7B7 | 85 55 | STA $55 | ||
F7B9 | C8 | INY | ||
BING07 | F7BA | 84 36 | STY $36 | Store pointer to next byte to convert (in .Y) into BYTCNT ($36). |
F7BC | 20 D0 F6 | JSR $F6D0 | JSR to PUT4GB ($F6D0) to convert the four bytes in $52/3/4/5 into their five GCR equivalents and store in buffer. Use the overflow buffer first and then use the data buffer. | |
F7BF | A4 36 | LDY $36 | Move next four bytes into the work area ($52/3/4/5) . | |
F7C1 | B1 2E | LDA ($2E),Y | ||
F7C3 | 85 52 | STA $52 | ||
F7C5 | C8 | INY | ||
F7C6 | F0 11 | BEQ $F7D9 | ||
F7C8 | B1 2E | LDA ($2E),Y | ||
F7CA | 85 53 | STA $53 | ||
F7CC | C8 | INY | ||
F7CD | B1 2E | LDA ($2E),Y | ||
F7CF | 85 54 | STA $54 | ||
F7D1 | C8 | INY | ||
F7D2 | B1 2E | LDA ($2E),Y | ||
F7D4 | 85 55 | STA $55 | ||
F7D6 | C8 | INY | ||
F7D7 | D0 E1 | BNE $F7BA | If more bytes to convert (.Y is count) branch back to BING07. | |
F7D9 | A5 3A | LDA $3A | Move data block checksum from DBID ($3A) and two off bytes ($00) into the work area ($53/4/5) NOTE: THE LAST DATA BYTE IS IN $52. | |
F7DB | 85 53 | STA $53 | ||
F7DD | A9 00 | LDA #$00 | ||
F7DF | 85 54 | STA $54 | ||
F7E1 | 85 55 | STA $55 | ||
F7E3 | 4C D0 F6 | JMP $F6D0 | JSR to PUT4GB ($F6D0) to convert the four bytes in $52/3/4/5 into their five GCR equivalents and store in buffer. | |
Convert GCR to binaryThis routine is used to decode 5 GCR bytes (used for recording on disk) into 4 normal 8-bit binary bytes. Decoding involves extracting 5 bits from one or two GCR bytes. The 4-bit nybble that is equivalent to it is found by looking in a table. The pattern of 5-bit segments in the 5 GCR bytes and the equivalent 4-bit nybbles in the four binary bytes are indicated below: Four 10 bit encoded bytes stored in buffer aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh Four normal 8 bit bytes stored in $56/7/8/9 AAAABBBB CCCCDDDD EEEEFFFF GGGGHHHH |
||||
GET4GB | F7E6 | A4 34 | LDY $34 | Load the first GCR byte (aaaaabbb) from (BUFPNT) ,Y, AND it with $F8 (11111000) to mask off the low bits (aaaaOOO). do three LSR's and store the result (OOOaaaaa) in GTAB ($56) |
F7E8 | B1 30 | LDA ($30),Y | ||
F7EA | 29 F8 | AND #$F8 | ||
F7EC | 4A | LSR | ||
F7ED | 4A | LSR | ||
F7EE | 4A | LSR | ||
F7EF | 85 56 | STA $56 | ||
F7F1 | B1 30 | LDA ($30),Y | Load the first GCR byte (aaaaabbb) from (BUFPNT) ,Y, AND it with $07 (00000111) to mask off the high bits (OOOOObbb). do two ASL's and store the result (OOObbbOO) in $57. | |
F7F3 | 29 07 | AND #$07 | ||
F7F5 | 0A | ASL | ||
F7F6 | 0A | ASL | ||
F7F7 | 85 57 | STA $57 | ||
F7F9 | C8 | INY | Increment Y and check if Y=0. If so, change BUFPNT so it points to the data buffer rather than the overflow buffer. | |
F7FA | D0 06 | BNE $F802 | ||
F7FC | A5 4E | LDA $4E | ||
F7FE | 85 31 | STA $31 | ||
F800 | A4 4F | LDY $4F | ||
F802 | B1 30 | LDA ($30),Y | Load the second GCR byte (bbcccccd) from (BUFPNT) ,Y, AND it with $C0 (11000000) to mask off the low bits (bbOOOOOO). do three ROL f s (OOOOOObb). OR it with the value in $57 (OOObbbOO). and store the result (OOObbbbb) back in $57. | |
F804 | 29 C0 | AND #$C0 | ||
F806 | 2A | ROL | ||
F807 | 2A | ROL | ||
F808 | 2A | ROL | ||
F809 | 05 57 | ORA $57 | ||
F80B | 85 57 | STA $57 | ||
F80D | B1 30 | LDA ($30),Y | Load the second GCR byte (bbcccccd) from (BUFPNT) ,Y, AND it with $3E (00111110) to mask off unwanted bits (OOcccccO). do one LSR and store the result (OOOccccc) in $58. | |
F80F | 29 3E | AND #$3E | ||
F811 | 4A | LSR | ||
F812 | 85 58 | STA $58 | ||
F814 | B1 30 | LDA ($30),Y | Load the second GCR byte (bbcccccd) from (BUFPNT) ,Y, AND it with $01 (00000001) to mask off unwanted bits (OOOOOOOd) , do four ASL's and store the result (OOOdOOOO) in $58. | |
F816 | 29 01 | AND #$01 | ||
F818 | 0A | ASL | ||
F819 | 0A | ASL | ||
F81A | 0A | ASL | ||
F81B | 0A | ASL | ||
F81C | 85 59 | STA $59 | ||
F81E | C8 | INY | ||
F81F | B1 30 | LDA ($30),Y | Load the third GCR byte (ddddeeee) from (BUFPNT) ,Y, AND it with $F0 (11110000) to mask off the low bits (ddddOOOO). do four LSR's (OOOOdddd). OR it with the value in $59 (OOOdOOOO). and store the result (OOOddddd) back in $59. | |
F821 | 29 F0 | AND #$F0 | ||
F823 | 4A | LSR | ||
F824 | 4A | LSR | ||
F825 | 4A | LSR | ||
F826 | 4A | LSR | ||
F827 | 05 59 | ORA $59 | ||
F829 | 85 59 | STA $59 | ||
F82B | B1 30 | LDA ($30),Y | Load the third GCR byte (ddddeeee) from (BUFPNT) ,Y, AND it with $0F (00001111) to mask off hi bits (OOOOeeee). do one ASL and store the result (OOOeeeeO) in $5A. | |
F82D | 29 0F | AND #$0F | ||
F82F | 0A | ASL | ||
F830 | 85 5A | STA $5A | ||
F832 | C8 | INY | ||
F833 | B1 30 | LDA ($30),Y | Load the fourth GCR byte (efffffgg) from (BUFPNT) ,Y, AND it with $80 (10000000) to mask off the low bits (eOOOOOOO). do two ROL's (OOOeOOOO). OR it with the value in $5A (OOOOeeee). and store the result (OOOeeeee) back in $5A. | |
F835 | 29 80 | AND #$80 | ||
F837 | 18 | CLC | ||
F838 | 2A | ROL | ||
F839 | 2A | ROL | ||
F83A | 29 01 | AND #$01 | ||
F83C | 05 5A | ORA $5A | ||
F83E | 85 5A | STA $5A | ||
F840 | B1 30 | LDA ($30),Y | Load the fourth GCR byte (efffffgg) from (BUFPNT) ,Y, AND it with $7C (01111100) to mask off unwanted bits (OfffffOO), do two LSR's and store the result (OOOfffff ) in $5B. | |
F842 | 29 7C | AND #$7C | ||
F844 | 4A | LSR | ||
F845 | 4A | LSR | ||
F846 | 85 5B | STA $5B | ||
F848 | B1 30 | LDA ($30),Y | Load the fourth GCR byte (efffffgg) from (BUFPNT),Y. AND it with $03 (00000011) to mask off unwanted bits (OOOOOOgg) , do three LSR's and store the result (OOOggOO0) in $5C. | |
F84A | 29 03 | AND #$03 | ||
F84C | 0A | ASL | ||
F84D | 0A | ASL | ||
F84E | 0A | ASL | ||
F84F | 85 5C | STA $5C | ||
F851 | C8 | INY | ||
F852 | D0 06 | BNE $F85A | ||
F854 | A5 4E | LDA $4E | Increment Y. If Y=0 change BUFPNT to point to the next buffer • | |
F856 | 85 31 | STA $31 | ||
F858 | A4 4F | LDY $4F | ||
F85A | B1 30 | LDA ($30),Y | Load the fifth GCR byte (ggghhhhh) from (BUFPNT),Y, AND it with $E0 (11100000) to mask off the low bit s (gggOOOOO). do four ROL's (OOOOOggg). OR it with the value in $5C (OOOggOOO). and store the result (OOOggggg) back in $5C. | |
F85C | 29 E0 | AND #$E0 | ||
F85E | 2A | ROL | ||
F85F | 2A | ROL | ||
F860 | 2A | ROL | ||
F861 | 2A | ROL | ||
F862 | 05 5C | ORA $5C | ||
F864 | 85 5C | STA $5C | ||
F866 | B1 30 | LDA ($30),Y | Load the fifth GCR byte (ggghhhhh) from (BUFPNT),Y. AND it with$1F (00011111) to mask off the high bi ts (OOOhhhhh), and store in $5D | |
F868 | 29 1F | AND #$1F | ||
F86A | 85 5D | STA $5D | ||
F86C | C8 | INY | ||
At this point the 40 bits that made up the 5 GCR bytes have been separated into eight 5-bit values that correspond to the eight 4-bit nybbles that will make up the four normal binary bytes. The 8 5-bit values are stored in $56-D. The following routines look up the 4 -bit hi nybbles in GCRHI ($F8A0) and the low nybbles in GCRLO (starts at $F8C0) |
||||
F86D | 84 34 | STY $34 | Load .X with the first 5-bit value from $56, load .A with 4-bit high nybble from GCRHI ,X, load X with a second five bit value from $57, OR .A with the four bit low nybble from GCRLO, X, and store the result in $52. | |
F86F | A6 56 | LDX $56 | ||
F871 | BD A0 F8 | LDA $F8A0,X | ||
F874 | A6 57 | LDX $57 | ||
F876 | 1D C0 F8 | ORA $F8C0,X | ||
F879 | 85 52 | STA $52 | ||
F87B | A6 58 | LDX $58 | Load X with the third 5-bit value from $58, load .A with 4-bit high nybble from GCRHI, X, load X with the fourth 5-bit value from $59, OR .A with the 4-bit low nybble from GCRLO, X and store the result in $53. | |
F87D | BD A0 F8 | LDA $F8A0,X | ||
F880 | A6 59 | LDX $59 | ||
F882 | 1D C0 F8 | ORA $F8C0,X | ||
F885 | 85 53 | STA $53 | ||
F887 | A6 5A | LDX $5A | Load X with the fifth 5-bit value from $5A, load .A with 4-bit high nybble from from GCRHI, X, load X with the second five bit value from $5B, OR .A with the four bit low nybble from GCRLO, X, and store the result in $54. | |
F889 | BD A0 F8 | LDA $F8A0,X | ||
F88C | A6 5B | LDX $5B | ||
F88E | 1D C0 F8 | ORA $F8C0,X | ||
F891 | 85 54 | STA $54 | ||
F893 | A6 5C | LDX $5C | Load .X with the seventh 5 value from $5C, load .A with 4-bit high nybble from GCRHI, X, load X with the second 5-bit value from $5D, OR .A with the four bit low nybble from GCRLO, X, and store the result in $55. | |
F895 | BD A0 F8 | LDA $F8A0,X | ||
F898 | A6 5D | LDX $5D | ||
F89A | 1D C0 F8 | ORA $F8C0,X | ||
F89D | 85 55 | STA $55 | ||
F89F | 60 | RTS | ||
NOTE: The five bit to four bit tables below have many $FF entries. These are the five bit codes that are not used. If one of these is found, it causes a byte decoding error |
||||
F8A0 | FF FF FF FF FF FF FF FF FF 80 00 10 FF C0 40 50 FF FF 20 30 FF F0 60 70 FF 90 A0 B0 FF D0 E0 FF FF FF FF FF FF FF FF FF FF 08 00 01 FF 0C 04 05 FF FF 02 03 FF 0F 06 07 FF 09 0A 0B FF 0D 0E FF | GCRHI($F8A0) & GCRLO($F8C0) Tables of 5 bit GCR to binary
| ||
Decode GCR data imageThis routine decoded the 69 GCR bytes stored in the overflow buffer ($10BB-FF) into normal 8-bit bytes. The decoded bytes are stored in a data buffer. |
||||
GCRBIN | F8E0 | A9 00 | LDA #$00 | Zero byte counter & lo bit of pointers |
F8E2 | 85 34 | STA $34 | ||
F8E4 | 85 2E | STA $2E | ||
F8E6 | 85 36 | STA $36 | ||
F8E8 | A9 01 | LDA #$01 | Set lo byte of pointer, NXTBF ($4E) to $BA and set the hi byte NXTPNT ($4F) to $01 so they point to the first byte of the GCR image in the overflow buffer. | |
F8EA | 85 4E | STA $4E | ||
F8EC | A9 BA | LDA #$BA | ||
F8EE | 85 4F | STA $4F | ||
F8F0 | A5 31 | LDA $31 | Set SAVPNT+1 ($2F) to point to the data buffer where the 8-bit bytes are to be stored. | |
F8F2 | 85 2F | STA $2F | ||
F8F4 | 20 E6 F7 | JSR $F7E6 | JSR to GET4GB ($F7E6) to convert the first five GCR bytes into binary, the header block ID, the header checksum, the sector #, and the track #. The decoded bytes appear in $52-5. | |
F8F7 | A5 52 | LDA $52 | Store header block ID code in BID ($38) | |
F8F9 | 85 38 | STA $38 | ||
F8FB | A4 36 | LDY $36 | Move the three decoded bytes from $53-55 into the buffer. Note that these bytes are NOT stored in the overflow buffer where the GCR image is stored. | |
F8FD | A5 53 | LDA $53 | ||
F8FF | 91 2E | STA ($2E),Y | ||
F901 | C8 | INY | ||
F902 | A5 54 | LDA $54 | ||
F904 | 91 2E | STA ($2E),Y | ||
F906 | C8 | INY | ||
F907 | A5 55 | LDA $55 | ||
F909 | 91 2E | STA ($2E),Y | ||
F90B | C8 | INY | ||
GCRB10 | F90C | 84 36 | STY $36 | Transfer byte pointer from .Y into BYTCNT ($36) . |
F90E | 20 E6 F7 | JSR $F7E6 | JSR to GET4GB ($F7E6) to convert the next five GCR bytes to normal and store them in $52-5. | |
F911 | A4 36 | LDY $36 | ||
F913 | A5 52 | LDA $52 | Move decoded data byte from $52 into the data buffer. | |
F915 | 91 2E | STA ($2E),Y | ||
F917 | C8 | INY | ||
F918 | F0 11 | BEQ $F92B | Test .Y to see if entire overflow buffer has been done. If done, branch to GCRB20 | |
F91A | A5 53 | LDA $53 | Move decoded data bytes from $53-5 into the data buffer. | |
F91C | 91 2E | STA ($2E),Y | ||
F91E | C8 | INY | ||
F91F | A5 54 | LDA $54 | ||
F921 | 91 2E | STA ($2E),Y | ||
F923 | C8 | INY | ||
F924 | A5 55 | LDA $55 | ||
F926 | 91 2E | STA ($2E),Y | ||
F928 | C8 | INY | ||
F929 | D0 E1 | BNE $F90C | If .Y is not $00, there is more to do so branch back to GCRB10. | |
GCRB20 | F92B | A5 53 | LDA $53 | Move header block checksum from $53 to CHKSUM ($3A) |
F92D | 85 3A | STA $3A | ||
F92F | A5 2F | LDA $2F | Restore buffer pointer and RTS. | |
F931 | 85 31 | STA $31 | ||
F933 | 60 | RTS | ||
Convert header to write imageThis routine creates a GCR image of a header block. It uses the header block ID code from HBID ($39) and the header information stored in $1A (checksum) , $19 (sector), $18 (track), $17 (ID2), and $16 (ID1). A final $00 byte is used as a final off byte. Four of the binary bytes are moved into a staging area and the subroutine PUT4GB ($F6D0) is used to convert these bytes to their GCR image and store them in the STAB buf f er ($24-D) |
||||
CONHDR | F934 | A5 31 | LDA $31 | Save current value of the buffer pointer BUFPNT+1 ($31) in SAVPNT+1 ($2F) . |
F936 | 85 2F | STA $2F | ||
F938 | A9 00 | LDA #$00 | Make BUFPNT+1 ($31) point to >STAB ($00) | |
F93A | 85 31 | STA $31 | ||
F93C | A9 24 | LDA #$24 | Make GCRPNT ($34) point to <STAB ($24) | |
F93E | 85 34 | STA $34 | ||
F940 | A5 39 | LDA $39 | Move hdr blk ID from HBID ($39) to $52 | |
F942 | 85 52 | STA $52 | ||
F944 | A5 1A | LDA $1A | Move checksum from $1A to $53 | |
F946 | 85 53 | STA $53 | ||
F948 | A5 19 | LDA $19 | Move sector from $19 to $54 | |
F94A | 85 54 | STA $54 | ||
F94C | A5 18 | LDA $18 | Move track from $18 to $55 | |
F94E | 85 55 | STA $55 | ||
F950 | 20 D0 F6 | JSR $F6D0 | JSR to PUT4GB ($F6D0) to convert the four bytes in $52-5 to 5 GCR bytes and store them at the start of STAB ($24-8). | |
F953 | A5 17 | LDA $17 | Move 2nd ID chr from $17 to $52 | |
F955 | 85 52 | STA $52 | ||
F957 | A5 16 | LDA $16 | Move 1st ID chr from $16 to $53 | |
F959 | 85 53 | STA $53 | ||
F95B | A9 00 | LDA #$00 | Store $00 off bytes into $54 & $55 | |
F95D | 85 54 | STA $54 | ||
F95F | 85 55 | STA $55 | ||
F961 | 20 D0 F6 | JSR $F6D0 | JSR to PUT4GB ($F6D0) to convert the four bytes in $52-5 to 5 GCR bytes and store them in STAB ($29-D). | |
F964 | A5 2F | LDA $2F | Restore the buffer pointer BUFPNT+1 ($31) to its previous value and RTS. | |
F966 | 85 31 | STA $31 | ||
F968 | 60 | RTS | ||
Utility routinesDisk controller error handlingThis routine is used to terminate all of the major disk controller routines. The inputs to this routine are: the error code (see table) in .A, the job buffer number in JOBN ($3F). and the GCRFLG ($50) (tells if the data in the buffer has been left in write image (1) or binary (0) form). The routine stuffs the error code into the job queue, converts the data back to binary (if necessary), starts time-out to turn off the drive motor, resets the stack pointer, and exits to $F2BE to begin scanning the job queue again. |
||||
ERRR | F969 | A4 3F | LDY $3F | Store error code in .A into job queue |
F96B | 99 00 00 | STA $0000,Y | ||
F96E | A5 50 | LDA $50 | Check GCRFLG ($50) to see if data left in GCR format. If not, branch to ERRR10. | |
F970 | F0 03 | BEQ $F975 | ||
F972 | 20 F2 F5 | JSR $F5F2 | JSR to WTOBIN ($F5F2) to convert data from GCR to normal. | |
ERRR10 | F975 | 20 8F F9 | JSR $F98F | JSR to TRNOFF ($F98F) to start the time- out to turn off the drive motor. |
F978 | A6 49 | LDX $49 | Use value from SAVSP ($49) to reset the stack pointer. | |
F97A | 9A | TXS | ||
F97B | 4C BE F2 | JMP $F2BE | JMP to TOP ($F2BE) to scan job queue. | |
Turn on disk drive motor |
||||
TURNON | F97E | A9 A0 | LDA #$A0 | Store $A0 into drive status, DRVST ($20) to indicate that the drive is ON but not yet up to speed (accelerating) . |
F980 | 85 20 | STA $20 | ||
F982 | AD 00 1C | LDA $1C00 | Set bit 2 (00000100) of DSKCNT ($1C00) to turn ON the drive motor. | |
F985 | 09 04 | ORA #$04 | ||
F987 | 8D 00 1C | STA $1C00 | ||
F98A | A9 3C | LDA #$3C | Store $3C into acceleration timer, ACLTIM ($48) to cause drive status to be set to up-to-speed after 1.5 seconds. (60 interrupts at .025 seconds each) | |
F98C | 85 48 | STA $48 | ||
F98E | 60 | RTS | ||
Turn off disk drive motor |
||||
TRNOFF | F98F | A6 3E | LDX $3E | Load .X with current drive # (0) |
F991 | A5 20 | LDA $20 | Set bit 4 (00010000) of the drive status DRVST ($20) to indicate DRIVE IS OFF! | |
F993 | 09 10 | ORA #$10 | ||
F995 | 85 20 | STA $20 | ||
F997 | A9 FF | LDA #$FF | Store $FF into acceleration timer to cause the drive to be turned OFF after 6.4 seconds. (255 interrupts x .025 sec) | |
F999 | 85 48 | STA $48 | ||
F99B | 60 | RTS | ||
Drive motor and head stepper control This routine is the last part of the main IRQ routine. As a result, it is executed every 10 milliseconds. Control is transferred to the routine by JMP instructions at the conclusion of the main disk controller routines. The RTS at the end of the routine transfers control to master IRQ routine at $FE7C. |
||||
END | F99C | AD 07 1C | LDA $1C07 | Move value in the 6522 's timer #1 high latch ($1C07) into timer #l's high bit counter ($1C05) |
F99F | 8D 05 1C | STA $1C05 | ||
F9A2 | AD 00 1C | LDA $1C00 | ||
F9A5 | 29 10 | AND #$10 | Test if write protect status has changed by loading the value from the 6522 's data PORT B($1C00), ANDing it with $10 and comparing it to the value in LWPT ($1E). If not equal, set flag for change in status, WPSW ($1C) to $01. | |
F9A7 | C5 1E | CMP $1E | ||
F9A9 | 85 1E | STA $1E | ||
F9AB | F0 04 | BEQ $F9B1 | ||
F9AD | A9 01 | LDA #$01 | ||
F9AF | 85 1C | STA $1C | ||
F9B1 | AD FE 02 | LDA $02FE | Test whether the head stepper is in (0 or 2) or out (1) of phase. The head's stepper motor moves half a track at a time. If the head is halfway between two tracks, the value stored in PHASE ($02FE) is 1. If the value in PHASE is 0, branch to END40 ($F9CB). If PHASE is 2, set it to $00 and branch to END40. If it is $01 set it to $02 & branch to DOSTEP ($FA2E) to move head half a track. | |
F9B4 | F0 15 | BEQ $F9CB | ||
F9B6 | C9 02 | CMP #$02 | ||
F9B8 | D0 07 | BNE $F9C1 | ||
F9BA | A9 00 | LDA #$00 | ||
F9BC | 8D FE 02 | STA $02FE | ||
F9BF | F0 0A | BEQ $F9CB | ||
F9C1 | 85 4A | STA $4A | ||
F9C3 | A9 02 | LDA #$02 | ||
F9C5 | 8D FE 02 | STA $02FE | ||
F9C8 | 4C 2E FA | JMP $FA2E | ||
F9CB | A6 3E | LDX $3E | Check CDRIVE ($3E) to see if the drive is active. If not active, branch to END33X to end the IRQ routine. | |
F9CD | 30 07 | BMI $F9D6 | ||
F9CF | A5 20 | LDA $20 | Load DRVST ($20) to see if the motor is ON and compare value with $20. If there is anything to do (result not equal), then branch to END10. | |
F9D1 | A8 | TAY | ||
F9D2 | C9 20 | CMP #$20 | ||
F9D4 | D0 03 | BNE $F9D9 | ||
END33X | F9D6 | 4C BE FA | JMP $FABE | JMP to END33 ($FABE) to end IRQ. |
END10 | F9D9 | C6 48 | DEC $48 | Something doing, so decrement the acceleration timer, ACLTIM ($48). and if drive is not yet up to speed, branch to END30. Since drive is up to speed, clear the not-up-to-speed bit (bit 7) of the drive status, DRVST ($20) . |
F9DB | D0 1D | BNE $F9FA | ||
F9DD | 98 | TYA | ||
F9DE | 10 04 | BPL $F9E4 | ||
F9E0 | 29 7F | AND #$7F | ||
F9E2 | 85 20 | STA $20 | ||
END20 | F9E4 | 29 10 | AND #$10 | AND the value of DRVST ($20) with $10 to test whether a time-out has occurred and it is time to turn off the drive motor. If not, branch to END30 ($F9FA). |
F9E6 | F0 12 | BEQ $F9FA | ||
F9E8 | AD 00 1C | LDA $1C00 | Turn off drive motor by loading .A with the value of DRVCNT ($1C00). ANDing it with $FB (to clear bit 2) and storing the result back in DRVCNT. | |
F9EB | 29 FB | AND #$FB | ||
F9ED | 8D 00 1C | STA $1C00 | ||
F9F0 | A9 FF | LDA #$FF | Store $FF in CDRIVE ($3E) to indicate there is no currently active drive. | |
F9F2 | 85 3E | STA $3E | ||
F9F4 | A9 00 | LDA #$00 | Set DRVST ($20) to $0 to indicate that the drive is switched OFF. Then branch to END33X ($F9D6) to end IRQ routine. | |
F9F6 | 85 20 | STA $20 | ||
F9F8 | F0 DC | BEQ $F9D6 | ||
END30 | F9FA | 98 | TYA | AND .A (contains drive status) with $40 to test if head must be moved. If the result is (no stepping needed) JMP to END33 ($FABE) to end the IRQ routine. If stepping is required f do an indirect JMP via NXTST ($0062) to the proper head stepping routine: SHORT - $FA3B - short step mode SETLE - $FA4E - settle head mode SSACL - $FA7B - accelerate mode SSRUN - $FA97 - fast stepping mode SSDEC - $FAA5 - decelerate mode |
F9FB | 29 40 | AND #$40 | ||
F9FD | D0 03 | BNE $FA02 | ||
F9FF | 4C BE FA | JMP $FABE | ||
FA02 | 6C 62 00 | JMP ($0062) | ||
Set up to step the head |
||||
INACT | FA05 | A5 4A | LDA $4A | Load .A with the number of steps to move the head from STEPS ($4A). If negative (>127), find the absolute value using the 2's complement. |
FA07 | 10 05 | BPL $FA0E | ||
FA09 | 49 FF | EOR #$FF | ||
FA0B | 18 | CLC | ||
FA0C | 69 01 | ADC #$01 | ||
INAC10 | FA0E | C5 64 | CMP $64 | Compare the number of steps to the value (usually $C8)in MINSTP ($64) to see if the distance is big enough to use the fast stepping mode. If the distance is large enough, branch to INA20 ($FA1C) . |
FA10 | B0 0A | BCS $FA1C | ||
FA12 | A9 3B | LDA #$3B | Not big enough so set up the pointer in NXTST ($62/3) to point to the short step routine, SHORT ($FA3B) and branch to DOSTEP ($FA2E) . | |
FA14 | 85 62 | STA $62 | ||
FA16 | A9 FA | LDA #$FA | ||
FA18 | 85 63 | STA $63 | ||
FA1A | D0 12 | BNE $FA2E | ||
INAC20 | FA1C | E5 5E | SBC $5E | Calculate the number of steps to do in fast stepping mode by subtracting the value in AS ($5E) from .A twice (for acceleration and deceleration). Store the result in RSTEPS ($61). Then move the number of steps needed for the head to accelerate from AS ($5E) to ACLSTP ($60). Finally set pointer in NXTST ($62/3) to point to the acceleration mode routine SSACL ($FA7B) |
FA1E | E5 5E | SBC $5E | ||
FA20 | 85 61 | STA $61 | ||
FA22 | A5 5E | LDA $5E | ||
FA24 | 85 60 | STA $60 | ||
FA26 | A9 7B | LDA #$7B | ||
FA28 | 85 62 | STA $62 | ||
FA2A | A9 FA | LDA #$FA | ||
FA2C | 85 63 | STA $63 | ||
DOSTEP | FA2E | A5 4A | LDA $4A | Load value from STEPS ($4A). If positive (<127). branch to STPIN ($FA63) to step the head inwards. |
FA30 | 10 31 | BPL $FA63 | ||
STPOUT | FA32 | E6 4A | INC $4A | Increment STEPS ($4A) to reduce number left to do by 1, load .X with the value from DSKCNT ($1C00) decrement it by 1, and branch to STP ($FA69) . |
FA34 | AE 00 1C | LDX $1C00 | ||
FA37 | CA | DEX | ||
FA38 | 4C 69 FA | JMP $FA69 | ||
Short distance head stepping |
||||
SHORT | FA3B | A5 4A | LDA $4A | Load the number of steps left to do from STEPS ($4A). If any left, branch to DOSTEP ($FA2E). If not, set NXTST pointer ($62/3) to point to the settle head routine SETLE ($FA4E) and store $05 in ACLSTP ($60) to set the settle time. Branch to END33 ($FABE) to end IRQ. |
FA3D | D0 EF | BNE $FA2E | ||
FA3F | A9 4E | LDA #$4E | ||
FA41 | 85 62 | STA $62 | ||
FA43 | A9 FA | LDA #$FA | ||
FA45 | 85 63 | STA $63 | ||
FA47 | A9 05 | LDA #$05 | ||
FA49 | 85 60 | STA $60 | ||
FA4B | 4C BE FA | JMP $FABE | ||
SETLE | FA4E | C6 60 | DEC $60 | Settle head routine. Decrement ACLSTP ($60) and if non-zero, brach to END33 ($FABE) to end IRQ. If zero, set drive status, DRVST ($20), to indicate that the drive is available for use by clearing bit 6. Set NXTST pointer ($62/3 ) to point to the head inactive routine ($FA05) and branch to END33 ($FABE). |
FA50 | D0 6C | BNE $FABE | ||
FA52 | A5 20 | LDA $20 | ||
FA54 | 29 BF | AND #$BF | ||
FA56 | 85 20 | STA $20 | ||
FA58 | A9 05 | LDA #$05 | ||
FA5A | 85 62 | STA $62 | ||
FA5C | A9 FA | LDA #$FA | ||
FA5E | 85 63 | STA $63 | ||
FA60 | 4C BE FA | JMP $FABE | ||
STPIN | FA63 | C6 4A | DEC $4A | Decrement STEPS ($4A) to reduce number left to do by 1. load .X with the value from DSKCNT($1C00) and increment it by 1 |
FA65 | AE 00 1C | LDX $1C00 | ||
FA68 | E8 | INX | ||
STP | FA69 | 8A | TXA | Transfer the value in .X to .A (this is DSKCNT+1 for a step in and DSKCNT-1 for a step out), AND the value with $03, and store it in TMP ($4B). Load DSKCNT, AND it with $FC to mask off bits & 1. OR it with TMP to set the new values for these bits, and store the result back in DSKCNT. JMP to END33 ($FABE) to end IRQ. |
FA6A | 29 03 | AND #$03 | ||
FA6C | 85 4B | STA $4B | ||
FA6E | AD 00 1C | LDA $1C00 | ||
FA71 | 29 FC | AND #$FC | ||
FA73 | 05 4B | ORA $4B | ||
FA75 | 8D 00 1C | STA $1C00 | ||
FA78 | 4C BE FA | JMP $FABE | ||
|
||||
Accelerate head routine |
||||
SSACL | FA7B | 38 | SEC | Set carry flag, load the 6522 Timer1 hi latch T1HL2 ($1C07), subtract the value. in AF ($5F; aceeleration factor), and store the result in T1HC2 ($1C05; timer1 hi counter). Decrement the number of acceleration steps left in ACLSTP ($60) - and if any steps left, branch to SSA10 |
FA7C | AD 07 1C | LDA $1C07 | ||
FA7F | E5 5F | SBC $5F | ||
FA81 | 8D 05 1C | STA $1C05 | ||
FA84 | C6 60 | DEC $60 | ||
FA86 | D0 0C | BNE $FA94 | ||
FA88 | A5 5E | LDA $5E | No steps left, so reset the number of acceleration steps left ACLSTP ($60) using the valuein AS ($5E) and set the NXTST pointer ($62/3) to point to the fast stepping routine, SSRUN ($FA97). | |
FA8A | 85 60 | STA $60 | ||
FA8C | A9 97 | LDA #$97 | ||
FA8E | 85 62 | STA $62 | ||
FA90 | A9 FA | LDA #$FA | ||
FA92 | 85 63 | STA $63 | ||
SSA10 | FA94 | 4C 2E FA | JMP $FA2E | JMP to DOSTEP ($FA2E) |
Fast stepping mode routine |
||||
SSRUN | FA97 | C6 61 | DEC $61 | Decrement number of steps left to do in RSTEPS ($61). If any left, branch to DOSTEP ($FA2E). Since none left, set the NXTST pointer ($62/3) to point to the decelerate routine SSDEC ($FAA5) and branch to DOSTEP ($FA2E) . |
FA99 | D0 F9 | BNE $FA94 | ||
FA9B | A9 A5 | LDA #$A5 | ||
FA9D | 85 62 | STA $62 | ||
FA9F | A9 FA | LDA #$FA | ||
FAA1 | 85 63 | STA $63 | ||
FAA3 | D0 EF | BNE $FA94 | ||
Decelerate head routine |
||||
SSDEC | FAA5 | AD 07 1C | LDA $1C07 | Load .A from the 6522 Timerl hi latch T1HL2 ($1C07). clear the carry flag, add the acceleration factor AF ($5F) , and store the result in T1HC2 ($1C05; timerl hi counter). Decrement the number of deceleration steps left ACLSTP ($60) and if any steps left, branch to SSA10. Since no steps left, set the NXTST pointer ($62/3) to point to the settle routine, SETLE ($FA4E). Set the number of acceleration steps left to $03 to allow settling time. |
FAA8 | 18 | CLC | ||
FAA9 | 65 5F | ADC $5F | ||
FAAB | 8D 05 1C | STA $1C05 | ||
FAAE | C6 60 | DEC $60 | ||
FAB0 | D0 E2 | BNE $FA94 | ||
FAB2 | A9 4E | LDA #$4E | ||
FAB4 | 85 62 | STA $62 | ||
FAB6 | A9 FA | LDA #$FA | ||
FAB8 | 85 63 | STA $63 | ||
FABA | A9 05 | LDA #$05 | ||
FABC | 85 60 | STA $60 | ||
END33 | FABE | AD 0C 1C | LDA $1C0C | Terminate the motor and stepper control routine by clearing bit 1 of the 6522 's peripheral control register, PCR2($1C0C) This force CA2 low which disables the SO line to the 6502. Finally, do an RTS to transfer control back to the main IRQ routine at $FE7C. |
FAC1 | 29 FD | AND #$FD | ||
FAC3 | 8D 0C 1C | STA $1C0C | ||
FAC6 | 60 | RTS | ||
This routine is used to format (NEW) a disketteThe code is executed in place (rather than moved into RAM and then executed as in the 4040). The IP FORMAT routine ($C8C6) sets up a JMP $FAC7 at the start of buffer #0, puts an EXECUTE ($E0) job into the job queue at $03, and then waits for the job to be completed. |
||||
FORMT | FAC7 | A5 51 | LDA $51 | Load .A from FTNUM ($51) to check if formatting has begun. If FTNUM>0, the formatting has begun so branch to L213 ($FAF5). If not, begin formatting by: Setting DRVST($20) to $60 (head is now stepping). storing $01 into DRVTRK ($22) to set the current track and into FTNUM ($51; format begun flag) . |
FAC9 | 10 2A | BPL $FAF5 | ||
FACB | A6 3D | LDX $3D | ||
FACD | A9 60 | LDA #$60 | ||
FACF | 95 20 | STA $20,X | ||
FAD1 | A9 01 | LDA #$01 | ||
FAD3 | 95 22 | STA $22,X | ||
FAD5 | 85 51 | STA $51 | ||
FAD7 | A9 A4 | LDA #$A4 | Do BUMP to track 1 by stepping head out 46 tracks. Store -92 (256-2*46) into STEPS ($4A) and clear bits & 1 of DSKCNT ($1C00) to set head phase to 00. | |
FAD9 | 85 4A | STA $4A | ||
FADB | AD 00 1C | LDA $1C00 | ||
FADE | 29 FC | AND #$FC | ||
FAE0 | 8D 00 1C | STA $1C00 | ||
FAE3 | A9 0A | LDA #$0A | Set CNT ($0620) to $0A to allow up to 10 errors before abort. | |
FAE5 | 8D 20 06 | STA $0620 | ||
FAE8 | A9 A0 | LDA #$A0 | Set NUM($0621/2) to 4000 ($0FA0) as a first guess at number of bytes that can be recorded on half a track. Exit with a JMP to END ($F99C) | |
FAEA | 8D 21 06 | STA $0621 | ||
FAED | A9 0F | LDA #$0F | ||
FAEF | 8D 22 06 | STA $0622 | ||
FAF2 | 4C 9C F9 | JMP $F99C | ||
L213 | FAF5 | A0 00 | LDY #$00 | On re-entry .A holds the track number (loaded from FTNUM). Compare it to the track in HDRPNT($32). If they match, we are on the correct track so branch to L214 ($FB00). If different, put the .A value (track we want) into HDRPNT ($32) and exit with a JMP to END ($F99C) . |
FAF7 | D1 32 | CMP ($32),Y | ||
FAF9 | F0 05 | BEQ $FB00 | ||
FAFB | 91 32 | STA ($32),Y | ||
FAFD | 4C 9C F9 | JMP $F99C | ||
L214 | FB00 | AD 00 1C | LDA $1C00 | Test bit 4 of DSKCNT ($1C00) to see if write protect is on. If 1, protect is not on so branch to TOPP ($FB0C). If 0, load .A with $08 to indicate a WRITE PROTECT error & JMP to FMTERR ($FDD3) . |
FB03 | 29 10 | AND #$10 | ||
FB05 | D0 05 | BNE $FB0C | ||
FB07 | A9 08 | LDA #$08 | ||
FB09 | 4C D3 FD | JMP $FDD3 | ||
TOPP | FB0C | 20 A3 FD | JSR $FDA3 | JSR to SYNCLR ($FDA3) to erase the track by writing 28*256 SYNC marks. |
FB0F | 20 C3 FD | JSR $FDC3 | JSR to WRTNUM ($FDC3) to write out NUM ($0621/22; value = 4000) SYNC marks. | |
FB12 | A9 55 | LDA #$55 | Store a non-sync character ($55) into the output port DATA2 ($1C01) and JSR to WRTNUM ($FDC3) to write NUM ($0621/2; value = 4000) non-sync bytes. | |
FB14 | 8D 01 1C | STA $1C01 | ||
FB17 | 20 C3 FD | JSR $FDC3 | ||
At this point the track will have one area that contains SYNC and another area that has non-sync characters like this:
The following routines time the SYNC and non-sync segments to determine how many characters can be written on the track, This is used to calculate the length of the gap between sectors(inter-sector) . |
||||
FB1A | 20 00 FE | JSR $FE00 | JSR to KILL ($FE00) to kill write mode. | |
FB1D | 20 56 F5 | JSR $F556 | JSR to SYNC ($F556) to wait for the start of the SYNC section. | |
FB20 | A9 40 | LDA #$40 | Set bit 6 of the 6522' s ACR1 ($180B) to set it up as a free running 100 micro- second timer. | |
FB22 | 0D 0B 18 | ORA $180B | ||
FB25 | 8D 0B 18 | STA $180B | ||
FB28 | A9 62 | LDA #$62 | ||
FB2A | 8D 06 18 | STA $1806 | ||
FB2D | A9 00 | LDA #$00 | ||
FB2F | 8D 07 18 | STA $1807 | ||
FB32 | 8D 05 18 | STA $1805 | ||
FB35 | A0 00 | LDY #$00 | Set .X and .Y to $00. They will hold the timer count. .X=least significant byte .Y=most significant bit | |
FB37 | A2 00 | LDX #$00 | ||
FWAIT | FB39 | 2C 00 1C | BIT $1C00 | Loop to wait for SYNC area |
FB3C | 30 FB | BMI $FB39 | ||
FWAIT2 | FB3E | 2C 00 1C | BIT $1C00 | Loop to wait for not-sync area |
FB41 | 10 FB | BPL $FB3E | ||
F000 | FB43 | AD 04 18 | LDA $1804 | Reset interrupt flags to start the timer |
Loop to time the non-sync area |
||||
F001 | FB46 | 2C 00 1C | BIT $1C00 | Check if SYNC here yet. If here, branch to F005 ($FB5C). If no SYNC yet, check IFR1 ($1804) to see if timer has timed out. If time not up yet, branch back to F001 ($FB46). If time is up, increment .X by 1 (and .Y if .X=0) and branch back to F000 ($FB43) to reset the timer. If . Y is 0, we have a count of 65535 which means we can't find a sync mark so abort by loading .A with $02 and JMP to FMTERR |
FB49 | 10 11 | BPL $FB5C | ||
FB4B | AD 0D 18 | LDA $180D | ||
FB4E | 0A | ASL | ||
FB4F | 10 F5 | BPL $FB46 | ||
FB51 | E8 | INX | ||
FB52 | D0 EF | BNE $FB43 | ||
FB54 | C8 | INY | ||
FB55 | D0 EC | BNE $FB43 | ||
FB57 | A9 02 | LDA #$02 | ||
FB59 | 4C D3 FD | JMP $FDD3 | ||
F005 | FB5C | 86 71 | STX $71 | Found a SYNC so store the non-sync times in T2 ($71/2). Reset .X and .Y to $00 and begin timing the SYNC area. |
FB5E | 84 72 | STY $72 | ||
FB60 | A2 00 | LDX #$00 | ||
FB62 | A0 00 | LDY #$00 | ||
F006 | FB64 | AD 04 18 | LDA $1804 | Reset interrupt flags to start the timer |
Loop to time the SYNC area |
||||
F007 | FB67 | 2C 00 1C | BIT $1C00 | Check if not-sync here yet. If here, go to F009 ($FB7D). If still have a SYNC, check IFR1 ($1804) to see if timer has timed out. If not time yet, branch back to F007 ($FB67). If time up, increment .X by 1 (and .Y if .X=0) and loop back to F006 ($FB64) to reset the timer. If . Y is 0, we have a count of 65535 which means we can't find no-SYNC. So abort: load .A with a $02 and JMP to FMTERR |
FB6A | 30 11 | BMI $FB7D | ||
FB6C | AD 0D 18 | LDA $180D | ||
FB6F | 0A | ASL | ||
FB70 | 10 F5 | BPL $FB67 | ||
FB72 | E8 | INX | ||
FB73 | D0 EF | BNE $FB64 | ||
FB75 | C8 | INY | ||
FB76 | D0 EC | BNE $FB64 | ||
FB78 | A9 02 | LDA #$02 | ||
FB7A | 4C D3 FD | JMP $FDD3 | ||
F009 | FB7D | 38 | SEC | Found non-sync. Calculate the difference between the SYNC and non-sync times. If the difference is less than 4, branch to COUNT ($FBB6). If the difference is more than 4, make NUM ($0261/2) the average of the two times and branch to TOPP ($FB0C) to try again. |
FB7E | 8A | TXA | ||
FB7F | E5 71 | SBC $71 | ||
FB81 | AA | TAX | ||
FB82 | 85 70 | STA $70 | ||
FB84 | 98 | TYA | ||
FB85 | E5 72 | SBC $72 | ||
FB87 | A8 | TAY | ||
FB88 | 85 71 | STA $71 | ||
FB8A | 10 0B | BPL $FB97 | ||
FB8C | 49 FF | EOR #$FF | ||
FB8E | A8 | TAY | ||
FB8F | 8A | TXA | ||
FB90 | 49 FF | EOR #$FF | ||
FB92 | AA | TAX | ||
FB93 | E8 | INX | ||
FB94 | D0 01 | BNE $FB97 | ||
FB96 | C8 | INY | ||
FB97 | 98 | TYA | ||
FB98 | D0 04 | BNE $FB9E | ||
FB9A | E0 04 | CPX #$04 | ||
FB9C | 90 18 | BCC $FBB6 | ||
FB9E | 06 70 | ASL $70 | ||
FBA0 | 26 71 | ROL $71 | ||
FBA2 | 18 | CLC | ||
FBA3 | A5 70 | LDA $70 | ||
FBA5 | 6D 21 06 | ADC $0621 | ||
FBA8 | 8D 21 06 | STA $0621 | ||
FBAB | A5 71 | LDA $71 | ||
FBAD | 6D 22 06 | ADC $0622 | ||
FBB0 | 8D 22 06 | STA $0622 | ||
FBB3 | 4C 0C FB | JMP $FB0C | ||
COUNT | FBB6 | A2 00 | LDX #$00 | Set .X and .Y to $00 to prepare to count the number of characters in the non-sync area. |
FBB8 | A0 00 | LDY #$00 | ||
FBBA | B8 | CLV | ||
CNT10 | FBBB | AD 00 1C | LDA $1C00 | Test bit 7 of DSKCNT ($1C00) to see if SYNC is here yet. If SYNC here, branch to CNT20 ($FBCE). If not, test the timer If not time, branch back to CNT10. If time for one character is up, increment .X (and .Y if needed). clear the timer flag (.V) and branch back to CNT10. If .Y=0 we have a count of 65535 so abort: load .A with $03 & JMP to FMTERR ($FDD3) |
FBBE | 10 0E | BPL $FBCE | ||
FBC0 | 50 F9 | BVC $FBBB | ||
FBC2 | B8 | CLV | ||
FBC3 | E8 | INX | ||
FBC4 | D0 F5 | BNE $FBBB | ||
FBC6 | C8 | INY | ||
FBC7 | D0 F2 | BNE $FBBB | ||
FBC9 | A9 03 | LDA #$03 | ||
FBCB | 4C D3 FD | JMP $FDD3 | ||
CNT20 | FBCE | 8A | TXA | Store the byte count (count*2) in TRAL ($0624/5) and turn off the 6522' s timer |
FBCF | 0A | ASL | ||
FBD0 | 8D 25 06 | STA $0625 | ||
FBD3 | 98 | TYA | ||
FBD4 | 2A | ROL | ||
FBD5 | 8D 24 06 | STA $0624 | ||
FBD8 | A9 BF | LDA #$BF | ||
FBDA | 2D 0B 18 | AND $180B | ||
FBDD | 8D 0B 18 | STA $180B | ||
Calculate the total number of bytes we need to record on this track:
|
||||
DS08 | FBE0 | A9 66 | LDA #$66 | Subtract this from the total we found and divide by the number of sectors to get the size of the gap between sectors. If the calculated gap is less than 4, it is too small so load .A with $05 and JMP to FMTERR ($FDD3). If it is big enough, store inter-sector gap in DTRCK ($0626) . |
FBE2 | 8D 26 06 | STA $0626 | ||
FBE5 | A6 43 | LDX $43 | ||
FBE7 | A0 00 | LDY #$00 | ||
FBE9 | 98 | TYA | ||
FBEA | 18 | CLC | ||
FBEB | 6D 26 06 | ADC $0626 | ||
FBEE | 90 01 | BCC $FBF1 | ||
FBF0 | C8 | INY | ||
FBF1 | C8 | INY | ||
FBF2 | CA | DEX | ||
FBF3 | D0 F5 | BNE $FBEA | ||
FBF5 | 49 FF | EOR #$FF | ||
FBF7 | 38 | SEC | ||
FBF8 | 69 00 | ADC #$00 | ||
FBFA | 18 | CLC | ||
FBFB | 6D 25 06 | ADC $0625 | ||
FBFE | B0 03 | BCS $FC03 | ||
FC00 | CE 24 06 | DEC $0624 | ||
FC03 | AA | TAX | ||
FC04 | 98 | TYA | ||
FC05 | 49 FF | EOR #$FF | ||
FC07 | 38 | SEC | ||
FC08 | 69 00 | ADC #$00 | ||
FC0A | 18 | CLC | ||
FC0B | 6D 24 06 | ADC $0624 | ||
FC0E | 10 05 | BPL $FC15 | ||
FC10 | A9 04 | LDA #$04 | ||
FC12 | 4C D3 FD | JMP $FDD3 | ||
FC15 | A8 | TAY | ||
FC16 | 8A | TXA | ||
FC17 | A2 00 | LDX #$00 | ||
FC19 | 38 | SEC | ||
FC1A | E5 43 | SBC $43 | ||
FC1C | B0 03 | BCS $FC21 | ||
FC1E | 88 | DEY | ||
FC1F | 30 03 | BMI $FC24 | ||
FC21 | E8 | INX | ||
FC22 | D0 F5 | BNE $FC19 | ||
FC24 | 8E 26 06 | STX $0626 | ||
FC27 | E0 04 | CPX #$04 | ||
FC29 | B0 05 | BCS $FC30 | ||
FC2B | A9 05 | LDA #$05 | ||
FC2D | 4C D3 FD | JMP $FDD3 | ||
FC30 | 18 | CLC | ||
FC31 | 65 43 | ADC $43 | ||
FC33 | 8D 27 06 | STA $0627 | ||
FC36 | A9 00 | LDA #$00 | Set sector counter SECT ($0628) to $00. | |
FC38 | 8D 28 06 | STA $0628 | ||
FC3B | A0 00 | LDY #$00 | ||
FC3D | A6 3D | LDX $3D | ||
MAK10 | FC3F | A5 39 | LDA $39 | Loop to create sector header images in buffer ($0300+) .Y is the pointer into the buffer (0 for sect #1) . Move sector ID code from HBID ($39) to $0300+Y ($0300 for #1) . |
FC41 | 99 00 03 | STA $0300,Y | ||
FC44 | C8 | INY | Increment .Y twice to skip the checksum and move sector number from SECT ($0628) to $0300+Y ($0302 for sector #1) . | |
FC45 | C8 | INY | ||
FC46 | AD 28 06 | LDA $0628 | ||
FC49 | 99 00 03 | STA $0300,Y | ||
FC4C | C8 | INY | Increment .Y and move the track number from FTNUM ($51) to $0300+Y ($0303 for sector #1) | |
FC4D | A5 51 | LDA $51 | ||
FC4F | 99 00 03 | STA $0300,Y | ||
FC52 | C8 | INY | Increment .Y and move ID2 from DSKID+1 ($13) to $0300+Y ($0304 for sector #1). | |
FC53 | B5 13 | LDA $13,X | ||
FC55 | 99 00 03 | STA $0300,Y | ||
FC58 | C8 | INY | Increment .Y and move ID1 from DSKID ($12) to $0300+Y ($0305 for sector #1). | |
FC59 | B5 12 | LDA $12,X | ||
FC5B | 99 00 03 | STA $0300,Y | ||
FC5E | C8 | INY | Increment .Y and store $0F in $0300+Y ($0306 for #1) as off byte. | |
FC5F | A9 0F | LDA #$0F | ||
FC61 | 99 00 03 | STA $0300,Y | ||
FC64 | C8 | INY | Increment .Y and store $0F in $0300+Y ($0307 for #1) as off byte. | |
FC65 | 99 00 03 | STA $0300,Y | ||
FC68 | C8 | INY | Increment .Y. calculate the header blk checksum and store it in $02F9+Y ($0302 for sector #1) | |
FC69 | A9 00 | LDA #$00 | ||
FC6B | 59 FA 02 | EOR $02FA,Y | ||
FC6E | 59 FB 02 | EOR $02FB,Y | ||
FC71 | 59 FC 02 | EOR $02FC,Y | ||
FC74 | 59 FD 02 | EOR $02FD,Y | ||
FC77 | 99 F9 02 | STA $02F9,Y | ||
FC7A | EE 28 06 | INC $0628 | Increment SECT ($0628) and compare it to number of sectors on track SECTR ($43) | |
FC7D | AD 28 06 | LDA $0628 | ||
FC80 | C5 43 | CMP $43 | ||
FC82 | 90 BB | BCC $FC3F | ||
FC84 | 98 | TYA | If done all images. save the number of sectors on this track onto the stack. Increment .X (becomes $01) and transfer it to .A (dummy data character) . | |
FC85 | 48 | PHA | ||
|
||||
CRTDAT | FC86 | E8 | INX | Loop to put 255 dummy data bytes ($01 's) into data buffer #2 ($0500+) |
FC87 | 8A | TXA | ||
FC88 | 9D 00 05 | STA $0500,X | ||
FC8B | E8 | INX | ||
FC8C | D0 FA | BNE $FC88 | ||
FC8E | A9 03 | LDA #$03 | Set the buffer pointer BUFPNT ($30/1) to point to the header block images ($0300) and JSR to FBTOG($FE30) to convert the header images to a GCR write image with no header block ID code. | |
FC90 | 85 31 | STA $31 | ||
FC92 | 20 30 FE | JSR $FE30 | ||
FC95 | 68 | PLA | Pull # of sectors from stack. transfer the value to .Y, and JSR to MOVUP($FDE5) to move the GCR header image stored in in buffer #0 69 bytes up in memory. Then JSR to MOVOVR ($FDF5) to move the 69 header image bytes from the overflow buffer into the low end of buffer #0. | |
FC96 | A8 | TAY | ||
FC97 | 88 | DEY | ||
FC98 | 20 E5 FD | JSR $FDE5 | ||
FC9B | 20 F5 FD | JSR $FDF5 | ||
FC9E | A9 05 | LDA #$05 | Set the buffer pointer BUFPNT ($30/1) to point to the dummy data block. JSR to CHKBLK ($F5E9) to calculate the data blk checksum, store it in CHKSUM, and JSR to BINGCR ($F78F) to convert the dummy data block into its GCR write image. | |
FCA0 | 85 31 | STA $31 | ||
FCA2 | 20 E9 F5 | JSR $F5E9 | ||
FCA5 | 85 3A | STA $3A | ||
FCA7 | 20 8F F7 | JSR $F78F | ||
FCAA | A9 00 | LDA #$00 | Begin formatting the track now! Set the pointer to the header GCR image HDRPNT ($32) to $00 so it points to the start of the first header image. | |
FCAC | 85 32 | STA $32 | ||
FCAE | 20 0E FE | JSR $FE0E | JSR to CLEAR ($FE0E) to wipe the track. | |
WRTSYN | FCB1 | A9 FF | LDA #$FF | Store $FF in PORT2 ($1C01) to be ready to write a sync character. Load .X with $05 (5 SYNC'S coming up!) |
FCB3 | 8D 01 1C | STA $1C01 | ||
FCB6 | A2 05 | LDX #$05 | ||
WRTS10 | FCB8 | 50 FE | BVC $FCB8 | Write out 5 sync marks |
FCBA | B8 | CLV | ||
FCBB | CA | DEX | ||
FCBC | D0 FA | BNE $FCB8 | ||
FCBE | A2 0A | LDX #$0A | Initialize .X to $0A (output 10 bytes) and set .Y with the value from HDRPNT ($32) so it points to the start of the header GCR image. | |
FCC0 | A4 32 | LDY $32 | ||
WRTS20 | FCC2 | 50 FE | BVC $FCC2 | Write out the 10 header characters |
FCC4 | B8 | CLV | ||
FCC5 | B9 00 03 | LDA $0300,Y | ||
FCC8 | 8D 01 1C | STA $1C01 | ||
FCCB | C8 | INY | ||
FCCC | CA | DEX | ||
FCCD | D0 F3 | BNE $FCC2 | ||
FCCF | A2 08 | LDX #$08 | Load .X with $08 (HARD SET VALUE!) NOTE: This means you can not easily change the header gap size! | |
WRTS30 | FCD1 | 50 FE | BVC $FCD1 | Loop to output eight $55 bytes to form the header gap (gapl) . |
FCD3 | B8 | CLV | ||
FCD4 | A9 55 | LDA #$55 | ||
FCD6 | 8D 01 1C | STA $1C01 | ||
FCD9 | CA | DEX | ||
FCDA | D0 F5 | BNE $FCD1 | ||
FCDC | A9 FF | LDA #$FF | Store $FF in PORT2 ($1C01) to be ready to write a sync mark. Load .X with $05 (5 SYNC's coming up!) | |
FCDE | A2 05 | LDX #$05 | ||
DBSYNC | FCE0 | 50 FE | BVC $FCE0 | Write out 5 sync marks |
FCE2 | B8 | CLV | ||
FCE3 | 8D 01 1C | STA $1C01 | ||
FCE6 | CA | DEX | ||
FCE7 | D0 F7 | BNE $FCE0 | ||
FCE9 | A2 BB | LDX #$BB | Initialize .X to $BB to point to the first byte of the overflow buffer (the start of the dummy data block) | |
WRTS40 | FCEB | 50 FE | BVC $FCEB | Loop to write out the 69 GCR bytes in the overflow buffer |
FCED | B8 | CLV | ||
FCEE | BD 00 01 | LDA $0100,X | ||
FCF1 | 8D 01 1C | STA $1C01 | ||
FCF4 | E8 | INX | ||
FCF5 | D0 F4 | BNE $FCEB | ||
FCF7 | A0 00 | LDY #$00 | ||
WRTS50 | FCF9 | 50 FE | BVC $FCF9 | Loop to write out the 256 GCR bytes in data buffer #2 ($0500+) |
FCFB | B8 | CLV | ||
FCFC | B1 30 | LDA ($30),Y | ||
FCFE | 8D 01 1C | STA $1C01 | ||
FD01 | C8 | INY | ||
FD02 | D0 F5 | BNE $FCF9 | ||
FD04 | A9 55 | LDA #$55 | Load .A with $55 and .X with the tail (inter-sector) gap from DTRCK ($0626) | |
FD06 | AE 26 06 | LDX $0626 | ||
WGP2 | FD09 | 50 FE | BVC $FD09 | Loop to write .X $55 characters to form the tail (inter-sector) gap. |
FD0B | B8 | CLV | ||
FD0C | 8D 01 1C | STA $1C01 | ||
FD0F | CA | DEX | ||
FD10 | D0 F7 | BNE $FD09 | ||
FD12 | A5 32 | LDA $32 | Advance the header pointer HDRPNT ($32/3 ) by 10 so it points to the start of the next header image. | |
FD14 | 18 | CLC | ||
FD15 | 69 0A | ADC #$0A | ||
FD17 | 85 32 | STA $32 | ||
FD19 | CE 28 06 | DEC $0628 | Decrement the sector counter SECT ($0628) by l and test to see if any more sectors to do. If more, branch back to WRTSYN to do the next sector. If no more, wait for the last byte to be written out and then JSR to KILL ($FE00) to switch to read mode. | |
FD1C | D0 93 | BNE $FCB1 | ||
FD1E | 50 FE | BVC $FD1E | ||
FD20 | B8 | CLV | ||
FD21 | 50 FE | BVC $FD21 | ||
FD23 | B8 | CLV | ||
FD24 | 20 00 FE | JSR $FE00 | ||
FD27 | A9 C8 | LDA #$C8 | Formatting done. Verify it! Set TRYS ($0623) to $C8 to limit the number of attempts to verify to 200. | |
FD29 | 8D 23 06 | STA $0623 | ||
COMP | FD2C | A9 00 | LDA #$00 | Set BUFPNT ($30/1) to point to the start of the headers in buffer #0 ($0300) and set SECT ($0628) with the # of sectors on this track from SECTR ($43) . |
FD2E | 85 30 | STA $30 | ||
FD30 | A9 03 | LDA #$03 | ||
FD32 | 85 31 | STA $31 | ||
FD34 | A5 43 | LDA $43 | ||
FD36 | 8D 28 06 | STA $0628 | ||
CMPR10 | FD39 | 20 56 F5 | JSR $F556 | JSR to SYNC($F556) to wait for a SYNC mark. Once found. set .X to $0A (there are 9 header characters to read) and .Y $00 (point to character in header image) |
FD3C | A2 0A | LDX #$0A | ||
FD3E | A0 00 | LDY #$00 | ||
CMPR15 | FD40 | 50 FE | BVC $FD40 | Loop to read header bytes and compare them to the image in the buffer. If any byte doesn't match, branch to CMPR20. |
FD42 | B8 | CLV | ||
FD43 | AD 01 1C | LDA $1C01 | ||
FD46 | D1 30 | CMP ($30),Y | ||
FD48 | D0 0E | BNE $FD58 | ||
FD4A | C8 | INY | ||
FD4B | CA | DEX | ||
FD4C | D0 F2 | BNE $FD40 | ||
FD4E | 18 | CLC | Header reads back OK so add 10 to BUFPNT ($30) so it points to next header image. | |
FD4F | A5 30 | LDA $30 | ||
FD51 | 69 0A | ADC #$0A | ||
FD53 | 85 30 | STA $30 | ||
FD55 | 4C 62 FD | JMP $FD62 | JMP to TSTDAT ($FD62) | |
CMPR20 | FD58 | CE 23 06 | DEC $0623 | Bad verify. Decrement TRYS ($0623). If more attempts left, branch back to COMP ($FD2C) to try again. If we have tried 200 times, abort: load .A with $06 and JMP to FMTERR ($FDD3) |
FD5B | D0 CF | BNE $FD2C | ||
FD5D | A9 06 | LDA #$06 | ||
FD5F | 4C D3 FD | JMP $FDD3 | ||
TSTDAT | FD62 | 20 56 F5 | JSR $F556 | Header OK so check the data block. JSR to SYNC ($F556) to wait for the data block SYNC mark. Once found, set .Y to $BB to point to the start of the data block image in the overflow buffer |
FD65 | A0 BB | LDY #$BB | ||
TST05 | FD67 | 50 FE | BVC $FD67 | Loop to read and verify the 69 GCR bytes in the overflow buffer. If no match, branch to CMPR20 ($FD58) and try again. |
FD69 | B8 | CLV | ||
FD6A | AD 01 1C | LDA $1C01 | ||
FD6D | D9 00 01 | CMP $0100,Y | ||
FD70 | D0 E6 | BNE $FD58 | ||
FD72 | C8 | INY | ||
FD73 | D0 F2 | BNE $FD67 | ||
FD75 | A2 FC | LDX #$FC | Overflow buffer OK so set .X to $FC (255-3; don't bother checking the OFF bytes at the end) . | |
TST10 | FD77 | 50 FE | BVC $FD77 | Loop to read and verify the 253 GCR bytes in data buffer #3. If no match, branch to CMPR20 ($FD58) and try again. |
FD79 | B8 | CLV | ||
FD7A | AD 01 1C | LDA $1C01 | ||
FD7D | D9 00 05 | CMP $0500,Y | ||
FD80 | D0 D6 | BNE $FD58 | ||
FD82 | C8 | INY | ||
FD83 | CA | DEX | ||
FD84 | D0 F1 | BNE $FD77 | ||
FD86 | CE 28 06 | DEC $0628 | Decrement the sector counter in SECT ($0628) by 1 and test to see if any more to do. If more, branch back to CMPR10 to do next sector. If no more, increment the track counter FTNUM ($51) and test if there are any more tracks to do. If all done, branch to FMTEND ($FD96). If more to do, JMP to END ($F99C) to step the head to the next track. | |
FD89 | D0 AE | BNE $FD39 | ||
FD8B | E6 51 | INC $51 | ||
FD8D | A5 51 | LDA $51 | ||
FD8F | C9 24 | CMP #$24 | ||
FD91 | B0 03 | BCS $FD96 | ||
FD93 | 4C 9C F9 | JMP $F99C | ||
FMTEND | FD96 | A9 FF | LDA #$FF | Set the track counter, FTNUM ($51) to $FF and the GCRFLG ($50) to 0. To flag a successful completion load .A with $01 and JMP to ERRR ($F969). Formatting and Verification Completed! |
FD98 | 85 51 | STA $51 | ||
FD9A | A9 00 | LDA #$00 | ||
FD9C | 85 50 | STA $50 | ||
FD9E | A9 01 | LDA #$01 | ||
FDA0 | 4C 69 F9 | JMP $F969 | ||
Formatting Subroutines |
||||
SYNCLR | FDA3 | AD 0C 1C | LDA $1C0C | Wipe track by writing 40*256 SYNC marks Set bits 6 & 7 of the 6522' s peripheral control register PCR2 ($1C0C). This latches the signal on the CB2 line. |
FDA6 | 29 1F | AND #$1F | ||
FDA8 | 09 C0 | ORA #$C0 | ||
FDAA | 8D 0C 1C | STA $1C0C | ||
FDAD | A9 FF | LDA #$FF | Store $FF in the data direction register DDRA2 ($1C03) to make PORT A an output- port and put $FF in the data port DATA2 ($1C01) to produce SYNC characters. | |
FDAF | 8D 03 1C | STA $1C03 | ||
FDB2 | 8D 01 1C | STA $1C01 | ||
FDB5 | A2 28 | LDX #$28 | Initialize .X to $28 (hi counter) and .Y to $00 (lo counter). | |
FDB7 | A0 00 | LDY #$00 | ||
SYC10 | FDB9 | 50 FE | BVC $FDB9 | Loop to write out 40*256 SYNC marks using .X & .Y as counters |
FDBB | B8 | CLV | ||
FDBC | 88 | DEY | ||
FDBD | D0 FA | BNE $FDB9 | ||
FDBF | CA | DEX | ||
FDC0 | D0 F7 | BNE $FDB9 | ||
FDC2 | 60 | RTS | RTS WARNING WRITE MODE LEFT ON | |
Write out NUM ($0621/2) bytes |
||||
WRTNUM | FDC3 | AE 21 06 | LDX $0621 | Load .X with the LSB and .Y with the MSB of NUM ($0621/2) . |
FDC6 | AC 22 06 | LDY $0622 | ||
WRTN10 | FDC9 | 50 FE | BVC $FDC9 | Loop to write out what ever is in the data port DATA2 ($1C03) NUM times using .X and .Y as counters |
FDCB | B8 | CLV | ||
FDCC | CA | DEX | ||
FDCD | D0 FA | BNE $FDC9 | ||
FDCF | 88 | DEY | ||
FDD0 | 10 F7 | BPL $FDC9 | ||
FDD2 | 60 | RTS | RTS | |
Handles format errors |
||||
FMTERR | FDD3 | CE 20 06 | DEC $0620 | Decrement the retry counter CNT ($0620) and, if no tries left, branch to FMTE10. If any left, JMP to END($F99C) to do any stepping required and try again. |
FDD6 | F0 03 | BEQ $FDDB | ||
FDD8 | 4C 9C F9 | JMP $F99C | ||
FMTE10 | FDDB | A0 FF | LDY #$FF | Set the track counter FTNUM^($51) to $FF and the GCRFLG ($50) to and JMP to ERRR ($F969) . |
FDDD | 84 51 | STY $51 | ||
FDDF | C8 | INY | ||
FDE0 | 84 50 | STY $50 | ||
FDE2 | 4C 69 F9 | JMP $F969 | ||
Move .Y bytes in buffer #0 up 69 bytes |
||||
MOVUP | FDE5 | B9 00 03 | LDA $0300,Y | Loop to move .Y characters in buffer #0 ($0300+) up 69 memory locations in RAM. |
FDE8 | 99 45 03 | STA $0345,Y | ||
FDEB | 88 | DEY | ||
FDEC | D0 F7 | BNE $FDE5 | ||
FDEE | AD 00 03 | LDA $0300 | Move byte from $0300 to $0345. RTS Move 69 bytes from overflow buffer into the bottom of the data buffer pointed to by BUFPNT ($30/1) | |
FDF1 | 8D 45 03 | STA $0345 | ||
FDF4 | 60 | RTS | ||
MOVOVR | FDF5 | A0 44 | LDY #$44 | Load .Y with $44 (68) |
FDF7 | B9 BB 01 | LDA $01BB,Y | Loop to move 69 bytes from $01BB+ into the data buffer. RTS | |
FDFA | 91 30 | STA ($30),Y | ||
FDFC | 88 | DEY | ||
FDFD | 10 F8 | BPL $FDF7 | ||
FDFF | 60 | RTS | ||
Disable write mode |
||||
KILL | FE00 | AD 0C 1C | LDA $1C0C | Set bits 5, 6 and 7 of the 6522' s PCR2 ($1C0C) to set CB2 high. Store in the data direction register DDRA2 ($1C03) to make PORT A an input port. RTS |
FE03 | 09 E0 | ORA #$E0 | ||
FE05 | 8D 0C 1C | STA $1C0C | ||
FE08 | A9 00 | LDA #$00 | ||
FE0A | 8D 03 1C | STA $1C03 | ||
FE0D | 60 | RTS | ||
Wipe track with non-sync characters |
||||
CLEAR | FE0E | AD 0C 1C | LDA $1C0C | Clear (zero) bit 5 of the 6522' s PCR2 ($1C0C). This forces CB2 low. |
FE11 | 29 1F | AND #$1F | ||
FE13 | 09 C0 | ORA #$C0 | ||
FE15 | 8D 0C 1C | STA $1C0C | ||
FE18 | A9 FF | LDA #$FF | Store $FF in the data direction register DDRA2 ($1C03) to set output mode and put $55 in the data port DATA2 ($1C01) to write non-sync characters. | |
FE1A | 8D 03 1C | STA $1C03 | ||
FE1D | A9 55 | LDA #$55 | ||
FE1F | 8D 01 1C | STA $1C01 | ||
FE22 | A2 28 | LDX #$28 | Initialize .X to $28 (hi counter) and .Y to $00 (lo counter). | |
FE24 | A0 00 | LDY #$00 | ||
CLER10 | FE26 | 50 FE | BVC $FE26 | Loop to write out 40*256 non-sync characters using .X & .Y as counters. |
FE28 | B8 | CLV | ||
FE29 | 88 | DEY | ||
FE2A | D0 FA | BNE $FE26 | ||
FE2C | CA | DEX | ||
FE2D | D0 F7 | BNE $FE26 | ||
FE2F | 60 | RTS | RTS -- WARNING WRITE MODE LEFT ON -- | |
Convert header images in buffer #0 into GCR form without the header ID code. |
||||
FBTOG | FE30 | A9 00 | LDA #$00 | Zero the low byte of the buffer pointers pointers BUFPNT($31) and SAVPNT ($2E) and the byte counter BYTCNT ($36) . |
FE32 | 85 30 | STA $30 | ||
FE34 | 85 2E | STA $2E | ||
FE36 | 85 36 | STA $36 | ||
FE38 | A9 BB | LDA #$BB | Set the GCR pointer GCRPNT ($34) to $BB so it points to the first character in the overflow buffer ($01BB+) . | |
FE3A | 85 34 | STA $34 | ||
FE3C | A5 31 | LDA $31 | Save the hi byte of the buffer pointer BUFPNT ($31) into SAVPNT ($2F) and then set BUFPNT to $01 to point to the over- flow buffer. | |
FE3E | 85 2F | STA $2F | ||
FE40 | A9 01 | LDA #$01 | ||
FE42 | 85 31 | STA $31 | ||
FBG10 | FE44 | A4 36 | LDY $36 | Loop to move 4 bytes at a time into the staging area $52-55 and then do a JSR to PUT4BG ($F6D0) to convert them into five GCR bytes and store them in the overflow or data buffer. Terminate the routine with a JMP to PUT4BG to convert and store the last four. |
FE46 | B1 2E | LDA ($2E),Y | ||
FE48 | 85 52 | STA $52 | ||
FE4A | C8 | INY | ||
FE4B | B1 2E | LDA ($2E),Y | ||
FE4D | 85 53 | STA $53 | ||
FE4F | C8 | INY | ||
FE50 | B1 2E | LDA ($2E),Y | ||
FE52 | 85 54 | STA $54 | ||
FE54 | C8 | INY | ||
FE55 | B1 2E | LDA ($2E),Y | ||
FE57 | 85 55 | STA $55 | ||
FE59 | C8 | INY | ||
FE5A | F0 08 | BEQ $FE64 | ||
FE5C | 84 36 | STY $36 | ||
FE5E | 20 D0 F6 | JSR $F6D0 | ||
FE61 | 4C 44 FE | JMP $FE44 | ||
FE64 | 4C D0 F6 | JMP $F6D0 | ||
Main system IRQ routine (IRQ vector points here)IRQ's are generated in two ways:
This routine tests for the source of the IRQ signal and branches to the correct ROM routine. |
||||
SYSIRQ | FE67 | 48 | PHA | Save .A,. X, and .Y on the stack |
FE68 | 8A | TXA | ||
FE69 | 48 | PHA | ||
FE6A | 98 | TYA | ||
FE6B | 48 | PHA | ||
FE6C | AD 0D 18 | LDA $180D | Test if IRQ caused by an ATN signal the serial bus by checking bit 1 of interrupt flag register of the 6522 handles the bus IFR1 ($180D). If thi bit is not set (1). there was no ATN signal so branch to IRQ10 ($FE76). I is set, JMP to the bus handling rout ATNIRQ ($E85F) . | |
FE6F | 29 02 | AND #$02 | ||
FE71 | F0 03 | BEQ $FE76 | ||
FE73 | 20 53 E8 | JSR $E853 | ||
IRQ10 | FE76 | AD 0D 1C | LDA $1C0D | Test if the 6522 timer has timed out- testing bit 7 of the interrupt flag register of the 6522 that serves as disk controller IFR2 ($1C0D). If the is not set, branch to IRQ20 ($FE7F) . it is set, do a JSR to the floppy di controller routines, LCC($F2B0). |
FE79 | 0A | ASL | ||
FE7A | 10 03 | BPL $FE7F | ||
FE7C | 20 B0 F2 | JSR $F2B0 | ||
IRQ20 | FE7F | 68 | PLA | Pull .A, .X, and .Y from the stack and do an RTI. |
FE80 | A8 | TAY | ||
FE81 | 68 | PLA | ||
FE82 | AA | TAX | ||
FE83 | 68 | PLA | ||
FE84 | 40 | RTI | ||
FE85 | 12 | Directory track number (18) | ||
FE86 | 04 | Number of bytes/ track in BAM | ||
FE87 | 04 | Offset of BAM in the sector | ||
FE88 | 90 | Offset of disk name in BAM sector | ||
Command Search Table |
||||
FE89 | 56 | V = Validate or collect disk | ||
FE8A | 49 | I = Initialize BAM & directory | ||
FE8B | 44 | D = Duplicate or backup disk (N.A.) | ||
FE8C | 4D | M = Memory operation (M-R,M-W r M-E) | ||
FE8D | 42 | B = Block operation (B-R,B-A,B-W,etc) | ||
FE8E | 55 | U = User jump commands (except U + & U-) | ||
FE8F | 50 | P = Position (for REL files) | ||
FE90 | 26 | & = Utility loader | ||
FE91 | 43 | C = Copy file (copy disk N.A. on 1541) | ||
FE92 | 52 | R = Rename file | ||
FE93 | 53 | S = Scratch file | ||
FE94 | 4E | N = New or format a diskette | ||
Command Jump Table |
||||
FE95 | 84 05 C1 F8 1B 5C 07 A3 F0 88 23 0D ED D0 C8 CA CC CB E2 E7 C8 CA C8 EE |
| ||
Structure images for commands |
||||
FEAD | 51 | %01010001 disk copy | ||
FEAE | DD | %11011101 rename a file (not parsed) | ||
FEAF | 1C | %00011100 scratch a file (not parsed) | ||
FEB0 | 9E | %10011110 new a diskette (not parsed) | ||
FEB1 | 1C | %00011100 load a file
| ||
Mode table (R/W/A/M) |
||||
FEB2 | 52 | Read mode | ||
FEB3 | 57 | Write mode | ||
FEB4 | 41 | Append | ||
FEB5 | 4D | Modify (read improperly closed file) | ||
Miscellaneous constants & tables in ROM |
||||
FEB6 | 44 53 50 55 4C 44 53 50 55 52 45 45 52 53 45 4C 51 47 52 4C |
| ||
FECA | 08 | LED mask for drive | ||
FECB | 00 | LED mask for drive 1 (N.A. on 1541) | ||
Error flag variables for use by bit |
||||
FECC | 00 | ER00 | ||
FECD | 3F | ER0 | ||
FECE | 7F | ER1 | ||
FECF | BF | ER2 | ||
FED0 | FF | ER3 | ||
Number of sectors/track in each zone |
||||
FED1 | 11 | 17 sectors/track in | ||
FED2 | 12 | 18 sectors/track in | ||
FED3 | 13 | 19 sectors/track in | ||
FED4 | 15 | 21 sectors/track in | ||
FED5 | 41 | DOS version number (65) | ||
FED6 | 04 | Number of different zones | ||
Zone boundaries (highest track# + 1) |
||||
FED7 | 24 | Track #36 - end of zone 4 (31-35) | ||
FED8 | 1F | Track #31 - end of zone 3 (25-30) | ||
FED9 | 19 | Track #25 - end of zone 2 (18-24) | ||
FEDA | 12 | Track #18 - end of zone 1 (01-17) | ||
FEDB | 01 FF FF 01 00 | Offsets for error recovery | ||
Hi byte of pointers to data buffers |
||||
FEE0 | 03 | Data buffer #0 ($0300-03FF) | ||
FEE1 | 04 | Data buffer #1 ($0400-04FF) | ||
FEE2 | 05 | Data buffer #2 ($0500-05FF) | ||
FEE3 | 06 | Data buffer #3 ($0600-06FF) | ||
FEE4 | 07 | Data buffer #4 ($0700-07FF) | ||
FEE5 | 07 | Data buffer #5 ($0700-07FF) | ||
FEE6 | FD | Checksum for $E and $F ROMs | ||
NMI vector points here |
||||
NMI | FEE7 | 6C 65 00 | JMP ($0065) | Do indirect jump to the address stored in VNMI ($0065). This vector points to XXXXXX ($XXXX) |
Patch for power-on errors |
||||
PEA7A | FEEA | 8D 00 1C | STA $1C00 | Store the value that is in .A on entry into the 6522' s data port 2, LEDPRT ($1C00; also called DSKCNT) and in the data direction register, LEDOUT ($1C02; also called DDRB2). Exit with a JMP to REA7D ($EA7D) to return to the LED blink routine . |
FEED | 8D 02 1C | STA $1C02 | ||
FEF0 | 4C 7D EA | JMP $EA7D | ||
Patch for 1541 disk with slow serial receive |
||||
SLOWD | FEF3 | 8A | TXA | Produce a 40 microseconds delay with a loop that counts .X down from 5 to 1. Exit with an RTS. |
FEF4 | A2 05 | LDX #$05 | ||
FEF6 | CA | DEX | ||
FEF7 | D0 FD | BNE $FEF6 | ||
FEF9 | AA | TAX | ||
FEFA | 60 | RTS | ||
FEFB | 20 AE E9 | Unused junk | ||
FEFE | 4C 9C E9 | Unused junk | ||
Patch to nmi routine to check for U+ and U- commands |
||||
NNMI | FF01 | AD 02 02 | LDA $0202 | Load .A with the second character in the command buffer CMDBUF+2 ($0202), Compare it with "-" and, if equal, branch to NNMI10 ($FF0D). If not a "-". subtract a " + " from it. If not zero, command must- be a real UI command so branch back to NMI ($FEE7) to do normal NMI. |
FF04 | C9 2D | CMP #$2D | ||
FF06 | F0 05 | BEQ $FF0D | ||
FF08 | 38 | SEC | ||
FF09 | E9 2B | SBC #$2B | ||
FF0B | D0 DA | BNE $FEE7 | ||
NNMI10 | FF0D | 85 23 | STA $23 | Store .A (contains zero or a "-") into DRVTRK+1 ($23) and do an RTS to continue |
FF0F | 60 | RTS | ||
FF10 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | Unused garbage | ||
Table of jump vectors to routines (lo byte/hi byte) |
||||
FFE6 | C6 C8 | FORMAT ROM routine $C8C6 | ||
FFE8 | 8F F9 | TRNOFF ROM routine $F98F | ||
FFEA | 5F CD | UBLKRD ROM routine $CD5F | ||
FFEC | 97 CD | UBLKWT ROM routine $CD97 | ||
FFEE | 00 05 | Link to buffer #2 $0500 | ||
FFF0 | 03 05 | Link to buffer #2 $0503 | ||
FFF2 | 06 05 | Link to buffer #2 $0506 | ||
FFF4 | 09 05 | Link to buffer #2 $0509 | ||
FFF6 | 0C 05 | Link to buffer #2 $050C | ||
FFF8 | 0F 05 | Link to buffer #2 $050F | ||
FFFA | 01 FF | NNMI ROM routine $FF01 | ||
FFFC | A0 EA | DSKINT ROM routine $EAA0 | ||
FFFE | 67 FE | SYSIRQ ROM routine $FE67 |