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 |