# Disk 6: Apple DOS - [Part I: The DOS Collection](#part-i-the-dos-collection) - [DOS Components](#dos-components) - [DOS Header File](#dos-collection-header-file) - [_SETRWTS](#the-_setrwts-subroutine) - [_FMGETPARM](#the-_fmgetparm-subroutine) - [_FMBUFSCAN](#the-_fmbufscan-subroutine) - [_SETPBUFFS](#the-_setpbuffs-subroutine) - [_NAMESTR](#the-_namestr-subroutine) - [_NAMESTR2](#the-_namestr2-subroutine) - [_FN2BUFF](#the-_fn2buff-subroutine) - [_FMNM2](#the-_fmnm2-subroutine) - [_BUFFCLEAR](#the-_buffclear-subroutine) - [_FMPSET](#the-_fmpset-subroutine) - [_FMPSETA](#the-_fmpseta-subroutine) - [_FMPGET](#the-_fmpget-subroutine) - [_FMPGETA](#the-_fmpgeta-subroutine) - [Required DOS Macros](#required-dos-macros) - [FMFIL](#the-fmfil-macro) - [FMNAM](#the-fmnam-macro) - [FRWB](#the-frwb-macro) - [FWRTB](#the-fwrtb-macro) - [FRDB](#the-frdb-macro) - [FRWR](#the-frwr-macro) - [FRDR](#the-frdr-macro) - [FWRTR](#the-fwrtr-macro) - [DOS File Manager Macros and Subroutines](#dos-file-manager-macros) - [FCAT](#the-fcat-macro) - [FULCK](#the-fulck-macro) - [FLOCK](#the-flock-macro) - [FDEL](#the-fdel-macro) - [FVFY](#the-fvfy-macro) - [FCLOS](#the-fclos-macro) - [FRENM](#the-frenm-macro) - [FOPEN](#the-fopen-macros) - [BLOAD](#the-bload-macro) - [FBLOAD](#the-fbload-subroutine) - [BSAVE](#the-bsave-macro) - [FBSAVE](#the-fbsave-subroutine) - [Miscellaneous DOS Macros and Subroutines](#miscellaneous-dos-macros) - [DVER](#the-dver-macro) - [DOSIN](#the-dosin-macro) - [ABAS](#the-abas-macro) - [IBEX](#the-ibex-macro) - [ABEX](#the-abex-macro) - [Part II: DOS Collection Demos](#part-ii-dos-collection-demos) - File Manager Demo - Miscellaneous DOS Macros Demo --- ## Part I: The DOS Collection The sixth disk of the AppleIIAsm library is dedicated to DOS operations. For the most part, the macros and subroutines here act as an abstraction layer between the lower level functions of DOS and the programmer. Unfortunately, this does carry with it some substantial overhead in terms of bytes used, but the ease of functionality is usually worth it unless memory is an extreme concerned. In such a case, the DOS collection can be narrowed to only the functions that are needed. There are a number of macros and subroutines that are likely to go unused by most programmers, as they are mostly meant for internal use by the collection. These are covered as part of this documentation, but are not the primary focus of functionality. Those macros and subroutines that are the primary focus includes functions for the following: - Disk Catalog - File Locking and Unlocking - File Deletion - File Verification - File Renaming - File Opening and Closing - Binary File Loading and Saving - DOS Version Checking - Integer and Applesoft Runtime Checking - RWTS Access --- ## DOS Components The DOS Collection contains the following components: - A head file that includes a number of hooks, vectors and subroutines that are necessary for the operation of the whole collection. - A macro library that is required to be included for using the rest of the collection. - Two further sets of macro files, MAC.DOSFM.ASM and MAC.DOSMORE.ASM. The former contains macros used for managing files while the latter contains miscellaneous macros related to DOS. - Two demo files that illustrate how all of the major macros are used. Note that this does not include macros that are meant for internal use. --- ## DOS Collection Header File | Condition | Value | | ------------- | ------------------------------------------------------------ | | Name | File: HEAD.DOS.ASM | | Type | Header File | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin 8 Pro | | OS | Apple DOS 3.3 | | Purpose | Provide appropriate hooks and routines for the DOS collection | | Dependencies | none | | Bytes | 584 | | Notes | none | | See Also | none | --- *DETAILS* The DOS Header file includes a number of required subroutines that are detailed later in this section. `LISTING 6.00: HEAD.DOS.ASM Hooks & Vectors Source` ```assembly * *``````````````````````````````* * HEAD.DOS.ASM * * * * THIS HEADER FILE IS USED BY * * THE DOS COLLECTION AS A * * REPOSITORY FOR VARIABLE * * SPACE, HOOKS, SUBROUTINES * * NECESSARY FOR THE REST OF * * THE COLLECTION AND OTHER * * MISCELLANEOUS TASKS. * * * * CURRENTLY, THIS COLLECTION * * HAS QUITE A BIT OF OVERHEAD * * IN TERMS OF BYTES. THIS WILL * * HOPEFULLY BE REDUCED IN * * FUTURE REVISIONS. * * * * NOTE THAT THE METHOD USED * * FOR FINDING AN EMPTY FILE * * BUFFER IS ADAPTED FROM A * * LISTING IN DON WORTH'S AND * * PETER LECHNER'S /BENEATH * * APPLE DOS AND BENEAT APPLE * * PRODOS 2020/. AS SUCH, THE * * LICENSE MAY VARY. * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * DATE: 07-MAY-2021 * * ASSEMBLER: MERLIN PRO 8 * * OS: DOS 3.3 * * * * SIZE: 584 BYTES (OVERHEAD) * * * * SUBROUTINES: * * * * _SETRWTS * * _FMGETPARM * * _FMBUFSCAN * * _SETPBUFFS * * _NAMESTR * * _NAMESTR2 * * _FN2BUFF * * _FMNM2 * * _BUFFCLEAR * * _FMPSET * * _FMPSETA * * _FMPGET * * _FMPGETA * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * *``````````````````````````````* * RWTS EQUATES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ]RWTSPTR EQU ADDR4 ; WORK POINTER FOR RWTS ROUTINES ]RWTSRD EQU 1 ; READ CODE FOR RWTS ]RWTSWR EQU 1 ; WRITE CODE FOR RWTS ]LOCRPL EQU $3E3 ; LOCATE RWTS PARAMLIST ]RWTS EQU $3D9 ; RWTS ROUTINE * ]RPLIOB EQU $0 ; IOB TYPE, ALWAYS $01 ]RPLSLT EQU $1 ; IOB SLOT * 16 ]RPLDRV EQU $2 ; IOB DRIVE ]RPLVOL EQU $3 ; IOB VOLUME (#0 FOR ANY) ]RPLTRK EQU $4 ; IOB TRACK ]RPLSEC EQU $5 ; IOB SECTOR ]RPLDCT EQU $6 ; IOB ADDR TO DCT ($6,$7) ]RPLBUF EQU $8 ; IOB ADDR TO BUFFER ($8,$9) ]RPLSIZ EQU $A ; IOB SIZE ($A,$B) ]RPLCMD EQU $C ; IOB COMMAND ]RPLCNL EQU $00 ; NULL COMMAND ]RPLCRD EQU $01 ; READ COMMAND ]RPLCWR EQU $02 ; WRITE COMMAND ]RPLCFM EQU $04 ; FORMAT COMMAND ]RPLRCD EQU $D ; IOB RETURN CODE ]RPLRWP EQU $10 ; WRITED PROTECTED ERROR ]RPLRVM EQU $20 ; VOLUME MISMATCH ERROR ]RPLRDE EQU $40 ; DRIVE ERROR ]RPLRRE EQU $80 ; READ ERROR ]RPLTVL EQU $E ; IOB TRUE VOLUME ]RPLPSL EQU $F ; IOB PREVIOUS SLOT ]RPLPDR EQU $10 ; IOB PREVIOUS DRIVE * *``````````````````````````````* * FILE PARAMETER LIST EQUATES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ]FMPADDR EQU $3DC ; FILE MGR PARAM ADDR GET ]FMRUN EQU $3D6 ; RUN FILE MAMAGER ROUTINE ]DOSWARM EQU $3D0 ; DOS WARM START * ]TYP_TXT EQU $00 ; FILE TYPE TEXT VALUE ]TYP_INT EQU $01 ; FILE TYPE INT VALUE ]TYP_APP EQU $02 ; FILE TYPE APPLESOFT VALUE ]TYP_BIN EQU $04 ; FILE TYPE BINARY VALUE ]TYP_REL EQU $08 ; FILE TYPE REL VALUE ]TYP_S EQU $10 ; FILE TYPE S VALUE ]TYP_A EQU $20 ; FILE TYPE A VALUE ]TYP_B EQU $40 ; FILE TYPE B VALUE * ]SC_NON EQU $00 ; SUBCODE NOTHING VALUE ]SC_RWB EQU $01 ; SUBCODE READ OR WRITE A BYTE VALUE ]SC_RWR EQU $02 ; SUBCODE READ OR WRITE RANGE VALUE ]SC_PRWB EQU $03 ; SUBCODE POSITION THEN RW 1 BYTE VAL ]SC_PRWR EQU $04 ; SUBCODE POSITION THEN RW RANGE VAL * ]FC_OPEN EQU $01 ; COMMAND CODE FOR OPEN ]FC_CLOS EQU $02 ; COMMAND CODE FOR CLOSE ]FC_READ EQU $03 ; COMMAND CODE FOR READ ]FC_WRIT EQU $04 ; COMMAND CODE FOR WRITE ]FC_DEL EQU $05 ; COMMAND CODE FOR DELETE ]FC_CAT EQU $06 ; COMMAND CODE FOR CATALOG ]FC_LOCK EQU $07 ; COMMAND CODE FOR LOCK ]FC_UNLK EQU $08 ; COMMAND CODE FOR UNLOCK ]FC_REN EQU $09 ; COMMAND CODE FOR RENAME ]FC_POS EQU $0A ; COMMAND CODE FOR POSITION ]FC_INIT EQU $0B ; COMMAND CODE FOR INIT ]FC_VFY EQU $0C ; COMMAND CODE FOR VERIFY * ]P_CMD EQU $00 ; PARAM COMMAND OFFSET ]P_REC EQU $02 ; PARAM RECORD OFFSET ]P_VOL EQU $04 ; PARAM VOLUME OFFSET ]P_DRV EQU $05 ; PARAM DRIVE OFFSET ]P_SLOT EQU $06 ; PARAM SLOT OFFSET ]P_TYPE EQU $07 ; PARAM TYPE OFFSET ]P_NAMAD EQU $08 ; PARAM NAME BUFFER ADDRESS OFFSET ]P_WORK EQU $0C ; PARAM WORKAREA BUFFER ADDRESS OFFSET ]P_TSLS EQU $0E ; PARAM TSLS BUFFER ADDRESS OFFSET ]P_DATA EQU $10 ; PARAM DATA BUFFER ADDRESS OFFSET ]P_RETC EQU $0A ; PARAM RETURN CODE OFFSET ]P_RDWR EQU $00 ; READ OR WRITE OFFSET ]P_SUBC EQU $01 ; PARAM SUBCODE OFFSET ]P_BOFF EQU $04 ; PARAM BYTE OFFSET OFFSET ]P_RLEN EQU $06 ; PARAM RANGE LENGTH OFFSET ]P_RADDR EQU $08 ; PARAM RANGE ADDRESS OFFSET ]P_BYTE EQU $08 ; PARAM SINGLE WRITE BYTE OFFSET ]P_DPAGE EQU $01 ; PARAM 1ST DOS PAGE ADDR OFFSET * JMP __DHEXIT ; {6C3B} PASS OVER ROUTINES * MSLOT DFB $60 ; {0C1B} MASTER SLOT MDRIVE DFB $2 ; {0C1B} MASTER DRIVE MTRACK DFB $11 ; {0C1B} MASTER TRACK FOR RWTS MSECTOR DFB $0 ; {0C1B} MASTER SECTOR FOR RWTS MBUFFER DFB $9000 ; {0C1B} MASTER BUFFER ADDRESS FOR RWTS DFB $9000/$100 ; {0C1B} MCMD DFB $1 ; {0C1B} MASTER COMMAND FOR RWTS MVOL DFB $0 ; {0C1B} MASTER VOLUME FOR RWTS * ]TEMP HEX 0000 ; {0C2B} ]TEMP2 HEX 0000 ; {0C2B} ]FPARM HEX 0000 ; {0C2B} FILE MGR PARAM ADDRESS ]FNBUF HEX 0000 ; {0C2B} FILE NAME BUFFER ]FWORK HEX 0000 ; {0C2B} FILE WORKAREA BUFFER ]FDATA HEX 0000 ; {0C2B} FILE DATA BUFFER ]FTSLS HEX 0000 ; {0C2B} FILE TRACK/SECTOR LIST BUFFER ]FNAME DS 30 ; {0C30B} FILENAME TEMP STORAGE ]FNAME2 DS 30 ; {0C30B} SECOND FILENAME BUFFER ``` --- ### THE _SETRWTS SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | -------------------------- | | Name | `_SETRWTS` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Set common RWTS parameters | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 142+ | | Bytes | 78 | | Notes | none | | See Also | none | --- *DETAILS* The `_SETRWTS` routine sets the parameters for the **Input/Output Control Block** **(IOB)** before calling the **Read/Write Track/Sector** **(RWTS)** Routine. For the most part, this is used internally, and is not meant to be used by the end programmer. The following parameters are set in the **IOB** via the values given in global variables, which are set via another routine: - Slot - Drive - Volume - Track - Sector - Buffer - Command While the DOS collection makes knowing the format of the **Input/Output Control Block** unnecessary, there may be cases where one needs to access DOS at a lower level. Thus, the format of the **IOB** is listed here: **INPUT / OUTPUT CONTROL BLOCK** | Byte | Description | |------------------|------------------------| |00| Table type, must always be #00 | |01| Slot number * 16 ($10, $20, $30, $40, $50, $60, $70) | |02| Drive number | |03| Volume number (#00 for any) | |04| Track number | |05| Sector number | |06-07| Address of the Device Characteristics Table (DCT) | |08-09| Address of the 256 byte buffer for READ/WRITE | |0A| Unused | |0B| Byte count for partial sector | |0C| Command Code:
#$00 = SEEK
#$01 = READ
#$02 = WRITE
#$04 = FORMAT | |0D| Return Code. The CARRY flag is set upon returning from RWTS to indicate that an error has occurred. The following values are passed here to communicate the type of error:
#$00 = No error
#$08 = Initialization error
#$10 = Write protect error
#$20 = Volume mismatch
#$40 = Drive error
#$80 = Read error | |0E| Volume number last accessed | |0F| Slot number last accessed * 16 | |10| Drive number last accessed | While the **Device Characteristics Table (DCT)** is almost always the same and should remain unchanged (for a Disk II drive), its format is also listed here for reference: **DEVICE CHARACTERISTICS TABLE** | Byte | Description | |--------|-------------------| |00| Device Type (should be #$00) | |01| Phases per track (should be #$01) | |02-03| Motor on time count (should be #$EFD8) | `LISTING 6.01: HEAD.DOS.ASM _SETRWTS Routine Source` ```assembly * *``````````````````````````````* * _SETRWTS * * * * SET THE RWTS IOB PARAMETERS * * * * INPUT * * * * NONE. * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 142+ * * SIZE: 78 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _SETRWTS JSR ]LOCRPL ; {6C3B} LOCATE RWTS PARAMETER LIST STY ]RWTSPTR ; {4C3B} SAVE POINTER LOW AND HIGH STA ]RWTSPTR+1 ; {4C3B} LDA MSLOT ; {4C3B} GET DEFAULT SLOT ASL ; {2C1B} MULTIPLY BY 16 ASL ; {2C1B} TO GET APPROPRIATE VALUE ASL ; {2C1B} ASL ; {2C1B} LDY #]RPLSLT ; {3C2B} LOAD IOB SLOT OFFSET STA (]RWTSPTR),Y ; {6C2B} STORE SLOT VAL AT OFFSET LDA MDRIVE ; {4C3B} LOAD DEFAULT DRIVE LDY #]RPLDRV ; {3C2B} GET IOB DRIVE OFFSET STA (]RWTSPTR),Y ; {6C2B} STORE DRIVE IN IOB LDA MTRACK ; {4C3B} GET MASTER TRACK LDY #]RPLTRK ; {3C2B} OFFSET IN PARAM LIST STA (]RWTSPTR),Y ; {6C2B} STORE TRACK IN IOB LDA MSECTOR ; {4C3B} GET MASTER SECTOR CMP #16 ; {3C2B} BIGGER THAN 16? BCC :SOK ; {3C2B} NOPE, IT'S OKAY LDA #0 ; {3C2B} ELSE YES, SO CLEAR STA MSECTOR ; {4C3B} MASTER SECTOR :SOK LDY #]RPLSEC ; {3C2B} OFFSET IN PARMLIST STA (]RWTSPTR),Y ; {6C2B} STORE SECTOR IN IOB LDY #]RPLBUF ; {3C2B} OFFSET IN PARAMLIST LDA MBUFFER ; {4C3B} GET LOW BYTE OF BUFFER ADDR STA (]RWTSPTR),Y ; {6C2B} STORE LOW BYTE OF BUFF IN IOB INY ; {2C1B} INCREASE OFFSET LDA MBUFFER+1 ; {4C3B} GET HIGH BYTE STA (]RWTSPTR),Y ; {6C2B} STORE HIGH BYTE IN IOB LDA MCMD ; {4C3B} GET RWTS MASTER COMMAND LDY #]RPLCMD ; {3C2B} OFFSET OF PARMLIST STA (]RWTSPTR),Y ; {6C2B} STORE COMMAND IN IOB LDA MVOL ; {4C3B} GET RWTS MASTER VOLUME LDY #]RPLVOL ; {3C2B} OFFSET STA (]RWTSPTR),Y ; {6C2B} STORE VOLUME IN IOB RTS ; {6C1B} ``` --- ### THE _FMGETPARM SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------- | | Name | `_FMGETPARM` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Get the FPL Address | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 20+ | | Bytes | 10 | | Notes | none | | See Also | `_SETPBUFFS` | --- *DETAILS* The `_FMGETPARM` subroutine gets the address of the **File Manager Parameter List (FPL)** and returns it in **.Y** (low byte) and **.A** (high byte), with the addition of storing it in the ]FPARM variable space. This is different from the usual passing of addresses in **.A** and **.X** due to the nature of how DOS was programmed; since this is used internally, however, this should not present a problem. If the format of the **File Manager Parameter List (FPL)** is needed, it is available under the `SETPBUFFS` entry. `LISTING 6.02: HEAD.DOS.ASM _FMGETPARM Routine Source` ```assembly * *``````````````````````````````* * _FMGETPARM (NATHAN RIGGS) * * * * GET THE ADDRESS OF THE FILE * * PARAMETER LIST. * * * * INPUT * * * * NONE. * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 20+ * * SIZE: 10 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMGETPARM * JSR ]FMPADDR ; {6C3B} GET PARAM ADDRESS STA ]FPARM+1 ; {4C3B} STORE HIGH BYTE STY ]FPARM ; {4C3B} STORE LOW BYTE RTS ; {6C1B} * ``` --- ### THE _FMBUFSCAN SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ----------------------- | | Name | `_FMBUFSCAN` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Find a free file buffer | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 211+ | | Bytes | 117 | | Notes | none | | See Also | `_BUFFCLEAR` | --- *DETAILS* The `_FMBUFSCAN` subroutine finds an open file buffer and stores the addresses to various necessary sections in the appropriate memory locations. Primarily, this includes the **File Workarea**, the **Filename Buffer**, the **Data Sector Buffer**, and the **T/S List Sector (TSLS) Buffer**. If no file buffers are available then the carry is set to indicate an error, and the memory locations are all cleared to zero. A file buffer is considered clear if the first byte of the filename buffer carries a value of **#0**. While the DOS collection makes it unnecessary to know the inner workings of DOS, it may be useful for the programmer to know the format of each file buffer. The format is as follows: |BYTE | DESCRIPTION| |--------------|--------------------| |000-0FF | Data Sector Buffer (256 bytes)| |100-1FF | T/S List Sector Buffer (256 bytes)| |200-22C | File Manager Workarea Buffer (45 bytes)| |22D-24A | File Name Buffer (30 bytes)| |24B-24C | Address of File Manager Work Area Buffer| |24D-24E | Address of T/S List Sector Buffer| |24F-250 | Address of Data Sector Buffer| |251-252 | Address of the File Name Buffer in the next File Buffer. If this is the last buffer available, then the value is #0000.| `LISTING 6.03: HEAD.DOS.ASM _FMBUFSCAN Routine Source` ```assembly * *``````````````````````````````* * _FMBUFSCAN (NATHAN RIGGS) * * * * FIND A FREE FILE BUFFER. IF * * NONE EXISTS, RETURN #0. * * * * INPUT * * * * NONE. * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 211+ * * SIZE: 117 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMBUFFSCAN * LDA $3D2 ; {4C3B} LOCATE DOS LOAD POINT STA ADDR1+1 ; {3C2B} STORE THIS AS FIRST FNAME BUFF LDY #0 ; {3C2B} LOW BYTE SHOULD START AT 0 STY ADDR1 ; {3C2B} :GBUF0 LDA (ADDR1),Y ; {6C2B} LOCATE NEXT DOS BUFFER PHA ; {3C1B} TEMPORARILY HOLD INY ; {2C1B} INCREASE .Y INDEX LDA (ADDR1),Y ; {6C2B} LOAD HIGH BYTE OF ADDRESS STA ADDR1+1 ; {3C2B} STORE HIGH BYTE IN ZERO PAGE PLA ; {3C1B} PULL BACK EARLIER VALUE STA ADDR1 ; {3C2B} STORE AS LOW BYTE ON ZERO BNE :GBUF ; {4C3B} FOUND A BUFFER LDA ADDR1+1 ; {3C2B} ELSE LOAD HIGH BYTE BEQ :NBUF ; {4C3B} IF ZERO, NO BUFFER :GBUF LDY #0 ; {3C2B} GET FILENAME FIRST CHAR LDA (ADDR1),Y ; {6C2B} FROM THE BUFFER BEQ :GOTBUF ; {3C2B} IF 0, THEN BUFFER IS UNUSED LDY #36 ; {3C2B} IF NOT, SKIP TO NEXT LINK BNE :GBUF0 ; {3C2B} AND RERUN THE SEARCH LOOP :GOTBUF LDA ADDR1 ; {3C2B} LOAD FNAME BUFFER LOW BYTE STA ]FNBUF ; {4C3B} STORE FILENAME BUFFER ADDRESS LDA ADDR1+1 ; {3C2B} READ THE HIGH BYTE STA ]FNBUF+1 ; {4C3B} AND STORE AS POINTER ADDRESS LDY #30 ; {3C2B} INDEX TO FILE MANAGER WORKAREA LDA (ADDR1),Y ; {6C2B} FOR CONVENIENT STORAGE STA ]FWORK ; {4C3B} STORE WORKAREA POINTER INY ; {2C1B} INCREASE .Y INDEX LDA (ADDR1),Y ; {6C2B} LOAD THE HIGH BYTE STA ]FWORK+1 ; {4C3B} AND HOLD IT IN ]FWORK INY ; {2C1B} POINTER TO T/S LIST SECTOR BUFF LDA (ADDR1),Y ; {6C2B} LOAD LOW BYTE OF TS BUFFER STA ]FTSLS ; {4C3B} HOLD POINTER IN MEMORY INY ; {2C1B} INCREASE .Y INDEX LDA (ADDR1),Y ; {6C2B} LOAD HIGH BYTE STA ]FTSLS+1 ; {4C3B} AND HOLD INY ; {6C2B} INC POINTER TO DATA BUFFER LDA (ADDR1),Y ; {6C2B} LOAD LOW BYTE OF ADDRESS STA ]FDATA ; {4C3B} STORE IN MEMORY INY ; {2C1B} INCREASE .Y INDEX LDA (ADDR1),Y ; {6C2B} LOAD THE HIGH BYTE STA ]FDATA+1 ; {4C3B} AND STORE AS WELL CLC ; {2C1B} CLR CARRY TO INDICATE NO ERR RTS ; {6C1B} :NBUF LDA #0 ; {4C3B} LOAD #0 AND CLEAR OUT STA ]FNBUF ; {4C3B} ALL OF THE ADDRESS POINTERS STA ]FNBUF+1 ; {4C3B} STA ]FWORK ; {4C3B} STA ]FWORK+1 ; {4C3B} STA ]FTSLS ; {4C3B} STA ]FTSLS+1 ; {4C3B} STA ]FDATA ; {4C3B} STA ]FDATA+1 ; {4C3B} SEC ; {2C1B} SET CARRY TO INDICATE ERR RTS ; {6C1B} * ``` --- ### THE _SETPBUFFS SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | -------------------------------------------------------- | | Name | `_SETPBUFFS` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Set the buffers in the File Manager Parameter List (FPL) | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 119+ | | Bytes | 64 | | Notes | none | | See Also | `_FMBUFSCAN` | --- *DETAILS* The `_SETPBUFFS` subroutine sets the buffer addresses in the **File Manager Parameter List (FPL)** to the appropriate addresses in an open file buffer, as set by `_FMBUFSCAN`. The buffers set include the **Filename Buffer**, the **TS/LS Buffer**, **Data Sector Buffer** and the **File Workarea Buffer**. The format of the **FPL** slightly changes depending on the command being called, and the number of minor differences are too many to list here for any useful purposes. For a detailed list of how the **FPL** is formatted according to call type, see Don Worth's and Pieter Lechner's *Beneath Apple DOS*. However, there is a general format to the **FPL**, as follows: **File Manager Parameter List (FPL)** | Byte | Description | |--------|-------------------| |00| Command/Call Type:
$01 = OPEN
$02 = CLOSE
$03 = READ
$04 = WRITE
$05 = DELETE
$06 = CATALOG
$07 = LOCK
$08 = UNLOCK
$09 = RENAME
$0A = POSITION
$0B = INIT
$0C = VERIFY | |01| Sub-command/Sub-Call Type for READ or WRITE
$00 = No operation
$01 = READ or WRITE a byte
$02 = READ or WRITE a range of bytes
$03 = POSITION then READ or WRITE a byte
$04 = POSITION then READ or WRITE a range of bytes | |02-09| Parameters change based on call type. | |0A| Return Code. Upon returning from the file manager, the CARRY flag is set to indicate a non-zero return code is present. The number here can then be accessed to further understand the return status.
$00 = No errors
$01 = Language Not Available
$02 = Bad call type
$03 = Bad sub-call type
$04 = Write protected
$05 = End of Data
$06 = File not found
$07 = Volume mismatch
$08 = Disk I/O error
$09 = Disk full
$0A = File locked | |0B| Unused | |0C-0D| Address of File Manager Workarea Buffer | |0E-0F| Address of the TS/LS Buffer | |10-11| Address of the Data Sector Buffer | `LISTING 6.04: HEAD.DOS.ASM _SETPBUFFS Routine Source` ```assembly * *``````````````````````````````* * _SETPBUFFS (NATHAN RIGGS) * * * * SET THE FILENAME BUFFER, * * TS/LS BUFFER, DATA BUFFER * * AND THE FILE WORKAREA * * BUFFER. * * * * INPUT * * * * NONE. * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 119+ * * SIZE: 64 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _SETPBUFFS * LDA ]FPARM ; {4C3B} GET PARAMATER ADDRESS LOW BYTE STA ADDR1 ; {3C2B} AND HOLD IN ZERO PAGE LDA ]FPARM+1 ; {4C3B} LOAD HIGH BYTE STA ADDR1+1 ; {3C2B} INTO ZERO PAGE TOO LDY #$10 ; {3C2B} POINT TO DATA BUFFER POINTER LDA ]FDATA ; {4C3B} LOAD DATA BUFFER ADDRESS LOW STA (ADDR1),Y ; {6C2B} COPY POINTER TO PARAM LOCATION INY ; {2C1B} INCREASE .Y INDEX LDA ]FDATA+1 ; {4C3B} LOAD DATA BUFFER ADDR HIGH BYTE STA (ADDR1),Y ; {6C2B} COPY TO PARAM LOCATION LDY #$08 ; {3C2B} POINT TO FILENAME BUFFER LDA ]FNBUF ; {4C3B} LOAD FILENAME BUFFER POINTER ADDR STA (ADDR1),Y ; {6C2B} AND COPY TO PARAM LOCATION INY ; {2C1B} INCREASE .Y POINTER LDA ]FNBUF+1 ; {4C3B} LOAD THE HIGH BYTE STA (ADDR1),Y ; {6C2B} AND COPY AS WELL LDY #$0E ; {3C2B} T/S LIST SECTOR BUFFER POINTER LDA ]FTSLS ; {4C3B} LOAD CURRENT POINTER LOW BYTE STA (ADDR1),Y ; {6C2B} AND COPY TO PARAM LOCATION INY ; {2C1B} INCREASE .Y INDEX LDA ]FTSLS+1 ; {3C2B} LOAD THE HIGH BYTE STA (ADDR1),Y ; {6C2B} AND COPY TO PARAM LOCATION LDY #$0C ; {3C2B} WORKAREA BUFFER OFFSET IN PARAM LDA ]FWORK ; {4C3B} LOAD CURRENT WORKAREA POINTER STA (ADDR1),Y ; {6C2B} COPY TO PARAMETER LIST INY ; {2C1B} INCREASE .Y INDEX LDA ]FWORK+1 ; {4C3B} LOAD HIGH BYTE STA (ADDR1),Y ; {6C2B} AND COPY AS WELL * RTS ; {6C3B} * ``` --- ### THE _NAMESTR SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `_NAMESTR` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Copy filename from standard string format to the 30-byte string expected by DOS | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 64+ | | Bytes | 42 | | Notes | none | | See Also | `_NAMESTR2` `_FN2BUFF` `_FMNM2` | --- *DETAILS* The `_NAMESTR` subroutine is an internal procedure for transferring a standard preceding length-byte string to a temporary fixed 30-byte memory address that fills the empty bytes with spaces (this is determined by subtracting the string length from 30, which equals the number of trailing spaces needed). This subroutine should be called prior to calling the File Manager, given that the filename is not the same as the previous call. `LISTING 6.05: HEAD.DOS.ASM _NAMESTR Routine Source` ```assembly * *``````````````````````````````* * _NAMESTR (NATHAN RIGGS) * * * * COPY FILENAME FROM STANDARD * * STRING TO THE 30-BYTE STRING * * EXPECTED BY DOS IN A TEMP * * MEMORY AREA. * * * * INPUT * * * * .A = FILENAME STR ADDR LOW * * .X = HIGH BYTE * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 64+ * * SIZE: 42 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _NAMESTR * LDY #0 ; {3C2B} STA ADDR1 ; {3C2B} CLEAR OUT ZERO LOCATION STX ADDR1+1 ; {3C2B} LDA (ADDR1),Y ; {6C2B} GET STRING LENGTH STA BPAR1 ; {3C2B} HOLD TEMP IN ZERO PAGE LDY #0 ; {3C2B} RESET .Y INDEX LDX #255 ; {3C2B} SET .X INDEX TO -1 :_NSLP1 INX ; {2C1B} INCREASE .X INDEX INY ; {2C1B} INCREASE .Y INDEX LDA (ADDR1),Y ; {6C2B} GET CHARACTER STA ]FNAME,X ; {5C3B} STORE AT Y-1 LOC IN HOLD AREA CPX #29 ; {3C2B} COMPARE TO MAX STRING LENGTH BEQ :_NSEXIT ; {3C2B} IF MAX IS REACHED, EXIT CPY BPAR1 ; {3C2B} OTHERWISE COMPARE TO STRING LENGTH BNE :_NSLP1 ; {3C2B} IF NOT EQUAL, RELOOP TO NEXT CHAR :_NSLP2 INX ; {2C1B} STILL INCREASE .X INDEX LDA #" " ; {4C3B} NEXT CHAR IS SPACE STA ]FNAME,X ; {5C3B} STORE IN NAME AREA AT .X CPX #29 ; {3C2B} CHECK NEW STRING LENGTH BNE :_NSLP2 ; {3C2B} IF < 30, KEEP LOOPING :_NSEXIT RTS ; {6C1B} * ``` --- ### THE _NAMESTR2 SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `_NAMESTR2` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Copy second filename from standard string
format to the 30-byte string expected by DOS | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 64+ | | Bytes | 42 | | Notes | none | | See Also | `_NAMESTR` `_FN2BUFF` `_FMNM2` | --- *DETAILS* The `_NAMESTR2` subroutine accomplishes the same task as `_NAMESTR`, but does so for a second filename that is needed for procedures like renaming a file. This subroutine will likely be merged with the `_NAMESTR` subroutine in future revisions. `LISTING 6.06: HEAD.DOS.ASM _NAMESTR2 Routine Source` ```assembly * *``````````````````````````````* * _NAMESTR2 (NATHAN RIGGS) * * * * FULFILLS THE SAME FUNCTION * * AS _NAMESTR, EXCEPT FOR A * * SECOND STRING USED BY CMDS * * LIKE RENAME. * * * * .A = STRING ADDR LOW BYTE * * .X = STRING ADDR HIGH BYTE * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 64+ * * SIZE: 42 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _NAMESTR2 * LDY #0 ; {3C2B} STA ADDR1 ; {3C2B} CLEAR OUT ZERO LOCATION STX ADDR1+1 ; {3C2B} LDA (ADDR1),Y ; {6C3B} GET STRING LENGTH STA BPAR1 ; {3C2B} HOLD TEMP IN ZERO PAGE LDY #0 ; {3C2B} RESET .Y INDEX LDX #255 ; {3C2B} SET .X INDEX TO -1 :_NSLP1 INX ; {2C1B} INCREASE .X INDEX INY ; {2C1B} INCREASE .Y INDEX LDA (ADDR1),Y ; {6C2B} GET CHARACTER STA ]FNAME2,X ; {5C2B} STORE AT Y-1 LOC IN HOLD AREA CPX #29 ; {3C2B} COMPARE TO MAX STRING LENGTH BEQ :_NSEXIT ; {3C2B} IF MAX IS REACHED, EXIT CPY BPAR1 ; {3C2B} OTHERWISE COMPARE TO STRING LENGTH BNE :_NSLP1 ; {3C2B} IF NOT EQUAL, RELOOP TO NEXT CHAR :_NSLP2 INX ; {2C1B} STILL INCREASE .X INDEX LDA #" " ; {4C3B} NEXT CHAR IS SPACE STA ]FNAME2,X ; {5C2B} STORE IN NAME AREA AT .X CPX #29 ; {2C2B} CHECK NEW STRING LENGTH BNE :_NSLP2 ; {3C2B} IF < 30, KEEP LOOPING :_NSEXIT RTS ; {6C1B} * ``` --- ### THE _FN2BUFF SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------- | | Name | `_FN2BUFF` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Copy temporary 30-byte filename to the filename buffer. | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 41+ | | Bytes | 22 | | Notes | none | | See Also | `_NAMESTR` `_NAMESTR2` `_FMNM2` | --- *DETAILS* The `_FN2BUFF` subroutine simply copies the 30-byte filename created by `_NAMESTR` to the filename buffer for use by the File Manager. `LISTING 6.07: HEAD.DOS.ASM _FN2BUFF Routine Source` ```assembly * *``````````````````````````````* * _FN2BUFF (NATHAN RIGGS) * * * * MOVE THE TEMPORARY 30-BYTE * * FILENAME STRING INTO THE * * FILENAME BUFFER OF THE FILE * * BUFFER IN USE. * * * * INPUT * * * * NONE. * * * * DESTROY: NZCIDV * * ^^^ ^ * * CYCLES: 41+ * * SIZE: 22 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FN2BUFF * LDA ]FNBUF ; {4C3B} LOAD FILENAME BUFFER ADDR STA ADDR2 ; {3C2B} STORE LOW IN ZERO LDA ]FNBUF+1 ; {4C3B} STA ADDR2+1 ; {3C2B} STORE HIGH IN ZERO LDY #255 ; {3C2B} SET .Y INDEX TO -1 :_LPC1 INY ; {2C1B} INCREASE .Y INDEX LDA ]FNAME,Y ; {5C2B} GET CHAR STORED IN NAME AREA STA (ADDR2),Y ; {6C2B} STORE IN FILENAME BUFFER CPY #29 ; {2C2B} IS THE END OF STRING REACHED? BNE :_LPC1 ; {3C2B} IF NO, KEEP LOOPING RTS ; {6C1B} * ``` --- ### THE _FMNM2 SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `_FMNM2` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Register the address of the second filename
to be used by the File Manager. | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 55+ | | Bytes | 30 | | Notes | none | | See Also | `_NAMESTR` `_NAMESTR2` `_FN2BUFF` | --- *DETAILS* The `_FMNM2` subroutine is functionally equivalent to the `_FN2BUFF` subroutine except for a second filename, which is usually a destination filename. Although equivalent, the process for `_FMNM2` is different than `_FN2BUFF` and therefore cannot be merged into a single subroutine. `LISTING 6.08: HEAD.DOS.ASM _FMNM2 Routine Source` ```assembly * *``````````````````````````````* * _FMNM2 (NATHAN RIGGS) * * * * REGISTER THE ADDRESS OF THE * * SECOND FILENAME IN THE FILE * * PARAMETER LIST. * * * * INPUT * * * * NONE. * * * * DESTROY: NZCIDV * * ^^^ ^ * * CYCLES: 55+ * * SIZE: 30 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMNM2 LDA #]FNAME2 ; {3C2B} LDX #>]FNAME2 ; {3C2B} STA ADDR2 ; {3C2B} LOW BYTE OF REC ADDRESS IN .A STX ADDR2+1 ; {3C2B} HIGH BYTE IN .X LDA ]FPARM ; {4C3B} LOAD PARAM ADDRESS STA ADDR1 ; {3C2B} AND HOLD IN ZERO PAGE LDA ]FPARM+1 ; {4C3B} ALSO DO FOR HIGH BYTE STA ADDR1+1 ; {3C2B} LDY #$02 ; {3C2B} OFFSET TO THE RECORD VARIABLE LDA ADDR2 ; {3C2B} LOAD LOW BYTE STA (ADDR1),Y ; {6C2B} AND STORE IN PARAM LIST INY ; {2C1B} INCREASE .Y INDEX LDA ADDR2+1 ; {3C2B} LOAD HIGH BYTE STA (ADDR1),Y ; {6C2B} AND STORE IN PARAM LIST RTS ; {6C1B} * ``` --- ### THE _BUFFCLEAR SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | -------------------------------------------- | | Name | `_BUFFCLEAR` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Clear the current file buffer for use again. | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 31+ | | Bytes | 17 | | Notes | none | | See Also | `_FMBUFFSCAN` | --- *DETAILS* The `_BUFFCLEAR` subroutine clears out the last used file buffer for use again in the future. It does this by replacing the first byte in the filename buffer with the value **#$00**, which indicates to DOS that the buffer is free. This subroutine should be called whenever a program is finished using a file and closes it; otherwise, the file buffer will not be cleared, and multiple uses of the file buffers will eventually result in error. `LISTING 6.09: HEAD.DOS.ASM _BUFFCLEAR Routine Source` ```assembly * *``````````````````````````````* * _BUFFCLEAR (NATHAN RIGGS) * * * * CLEAR THE FILE BUFFER THAT * * IS CURRENTLY IN USE SO THAT * * THE BUFFER MAY BE REUSED. * * * * INPUT * * * * NONE. * * * * CYCLES: 31+ * * SIZE: 17 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _BUFFCLEAR * LDA ]FNBUF ; {4C3B} GET FILENAME BUFFER ADDR STA ADDR2 ; {3C2B} STORE IN ZERO LDA ]FNBUF+1 ; {4C3B} DO SAME FOR HIGH BYTE STA ADDR2+1 ; {3C2B} LDA #0 ; {3C2B} RESET .A TAY ; {2C1B} AND .Y STA (ADDR2),Y ; {6C3B} STORE #00 IN FIRST SPOT RTS ; {6C1B} TO INDICATE EMPTY BUFFER * ``` --- ### THE _FMPSET SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------ | | Name | `_FMPSET` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Set a file parameter. | | Input | .A = Value
.Y = File Parameter Offset | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 30+ | | Bytes | 16 | | Notes | none | | See Also | `_FMPSETA` `_FMPGET` `_FMPGETA` | --- *DETAILS* The `_FMPSET` subroutine sets a file parameter in the **FPL** indicated by the offset held in the **.Y** register to the value held in the **.A** register. This only sets a single byte. `LISTING 6.10: HEAD.DOS.ASM _FMPSET Routine Source` ```assembly * *``````````````````````````````* * _FMPSET (NATHAN RIGGS) * * * * SET A FILE PARAMTER TO THE * * VALUE HELD IN .A AT THE * * OFFSET INDICATED BY .Y. * * * * INPUT * * * * .A = VALUE * * .Y = FILE PARAMETER OFFSET * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 30+ * * SIZE: 16 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMPSET ; .Y HOLDS THE OFFSET TAX ; {2C1B} .A HOLDS THE VALUE LDA ]FPARM ; {4C3B} LOAD FILE MGR PARAMETER LOW STA ADDR1 ; {3C2B} HOLD ON ZERO PAGE LDA ]FPARM+1 ; {4C3B} LOAD HIGH BYTE STA ADDR1+1 ; {3C2B} ONTO ZERO PAGE TXA ; {2C1B} RETURN VALUE BACK TO .A STA (ADDR1),Y ; {6C3B} STORE VALUE AT OFFSET IN PARAMS RTS ; {6C1B} * ``` --- ### THE _FMPSETA SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `_FMPSETA` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Set a file parameter. | | Input | .A = Value Low Byte
.X = Value High Byte
.Y = File Parameter Offset | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 46+ | | Bytes | 26 | | Notes | none | | See Also | `_FMPSET` `_FMPGET` `_FMPGETA` | --- *DETAILS* The `_FMPSETA` subroutine sets a file parameter address in the **FPL** indicated by the offset held in the **.Y** register to the value held in the **.A** register (low byte) and the **.X** register (high byte), setting a two consecutive bytes. `LISTING 6.11: HEAD.DOS.ASM _FMPSETA Routine Source` ```assembly * *``````````````````````````````* * _FMPSETA (NATHAN RIGGS) * * * * SET A TWO-BYTE VALUE, SUCH * * AS AN ADDRESS, IN THE FILE * * PARAMETER LIST. * * * * INPUT * * * * .A = LOWEST BYTE * * .X = HIGHEST BYTE * * .Y = OFFSET VALUE * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 46+ * * SIZE: 26 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMPSETA ; .Y HOLDS THE OFFSET STA ADDR2 ; {3C2B} .A HOLDS LOW BYTE OF ADDR STX ADDR2+1 ; {3C2B} .X HOLDS ADDR HIGH BYTE LDA ]FPARM ; {4C3B} LOAD FILE MGR PARAMETER LOW STA ADDR1 ; {3C2B} HOLD ON ZERO PAGE LDA ]FPARM+1 ; {4C3B} LOAD HIGH BYTE STA ADDR1+1 ; {3C2B} ONTO ZERO PAGE LDA ADDR2 ; {3C2B} STA (ADDR1),Y ; {6C3B} STORE VAL AT OFFSET IN PARAMS LDA ADDR2+1 ; {3C2B} INY ; {2C1B} STA (ADDR1),Y ; {6C3B} RTS ; {6C1B} * ``` --- ### THE _FMPGET SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | --------------------------------------- | | Name | `_FMPGET` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Retrieve a file parameter from the FPL. | | Input | .Y = File Parameter Offset | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 26+ | | Bytes | 14 | | Notes | none | | See Also | `_FMPGETA` `_FMPSET` `_FMPSETA` | --- *DETAILS* The `_FMPGET` subroutine retrieves a single byte from a given parameter in the **FPL**, as indicated by the offset held in **.Y**. `LISTING 6.12: HEAD.DOS.ASM _FMPGET Routine Source` ```assembly * *``````````````````````````````* * _FMPGET (NATHAN RIGGS) * * * * GET A VALUE RETURNED FROM * * THE FILE MANAGER AFTER IT * * RUNS. THIS VALUE IS HELD AT * * AN OFFSET IN THE FILE PARAM * * LIST. * * * * INPUT: * * * * .Y = OFFSET TO READ * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 26+ * * SIZE: 14 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMPGET ; OFFSET IS PASSED IN .Y LDA ]FPARM ; {4C3B} STA ADDR1 ; {3C2B} LDA ]FPARM+1 ; {4C3B} STA ADDR1+1 ; {3C2B} LDA (ADDR1),Y ; {6C3B} VALUE RETURNED IN .A RTS ; {6C1B} * ``` --- ### THE _FMPGETA SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | -------------------------------------------------------- | | Name | `_FMPGETA` | | Type | Subroutine | | File | `HEAD.DOS.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Retrieve a two-byte address file parameter from the FPL. | | Input | .Y = File Parameter Offset | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 42+ | | Bytes | 21 | | Notes | none | | See Also | `_FMPGET` `_FMPSET` `_FMPSETA` | --- *DETAILS* The `_FMPGETA` subroutine retrieves two consecutive bytes from the offset held in **.Y** in the **FPL**. This is usually an address; the low byte is returned in **.A** and the high byte is returned in **.X**. `LISTING 6.13: HEAD.DOS.ASM _FMPGETA Routine Source` ```assembly * *``````````````````````````````* * _FMPGETA (NATHAN RIGGS) * * * * RETRIEVE A 2-BYTE VALUE LIKE * * AN ADDRESS FROM THE FILE * * PARAMETER LIST AT THE GIVEN * * OFFSET. * * * * INPUT * * * * .Y = OFFSET INDEX * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 42+ * * SIZE: 21 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * _FMPGETA ; OFFSET PASSED IN .Y LDA ]FPARM ; {4C3B} STA ADDR1 ; {3C2B} LDA ]FPARM+1 ; {4C3B} STA ADDR1+1 ; {3C2B} LDA (ADDR1),Y ; {6C3B} GET LOW BYTE PHA ; {3C1B} HOLD ON STACK INY ; {2C1B} INCREASE INDEX LDA (ADDR1),Y ; {6C3B} GET HIGH BYTE TAX ; {2C1B} PASS BACK IN .X PLA ; {3C1B} PASS LOW IN .A RTS ; {6C1B} * ``` --- ## Required DOS Macros The MAC.DOSREQ.ASM file contains various macros that are required to be included (USE) in order for the entire DOS collection to function. This is unlike other collections, which usually do not require a separate macro file that the other macros and subroutines depend upon. While these macros could be replaced in each macro and subroutine with the appropriate code, the Merlin 8 Pro compiler would quickly run into memory management issues due to limitations on file size. Most of these macros call a combination of the subroutines found in the HEAD.DOS.ASM file, and should be used in place of calling the subroutines directly. `LISTING 6.20: MAC.DOSREQ.ASM Heading Source` ```assembly * *``````````````````````````````* * MAC.DOSREQ.ASM * * * * THESE MACROS ARE REQUIRED * * FOR USING THE DOS MACROS AND * * SUBROUTINES. GENERALLY, THIS * * INCLUDES LOW LEVEL ROUTINES * * AND MACRO SHORTCUTS TO SAVE * * MEMORY DURING ASSEMBLY. * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * DATE: 06-MAY-2021 * * ASSEMBLER: MERLIN 8 PRO * * OS: DOS 3.3 * * * * SUBROUTINE FILES USED * * * * * * LIST OF MACROS * * * * SRWTS : SET RWTS PARAMETERS * * GRWTS : RUN RWTS ROUTINE * * FMFIL : FILL FILE MGR PARAMS * * FMNAM : STRING TO PARAM AREA * * FRWB : BYTE READ/WRITE MAC * * FWRTB : WRITE A BYTE TO FILE * * FRDB : READ BYTE FROM FILE * * FRWR : RANGE READ/WRITE MAC * * FRDR : READ RANGE FROM FILE * * FWRTR : WRITE RANGE TO FILE * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ``` --- ### THE SRWTS MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `SRWTS` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Set common RWTS parameters. | | Input | ]1 = Slot
]2 = Drive
]3 = Volume
]4 = Track
]5 = Sector
]6 = Buffer Address
]7 = Command | | Output | none | | Dependencies | `_SETRWTS` | | Flags Destroyed | NZCV | | Cycles | 228+ | | Bytes | 141 | | Notes | none | | See Also | `_SETRWTS` | --- *DETAILS* The `SRWTS` macro sets the most common parameters used in the **IOB** before calling the **RWTS** routine. This includes the slot, drive, volume, track, sector, buffer address and **RWTS** command. If the volume is set to **#0**, then any volume will be acceptable for **RWTS**. `LISTING 6.21: MAC.DOSREQ.ASM SRWTS Macro Source` ```assembly * *``````````````````````````````* * SETRWTS * * * * SET THE PARAMETERS FOR RWTS. * * * * PARAMETERS * * * * ]1 = RWTS SLOT * * ]2 = RWTS DRIVE * * ]3 = RWTS VOLUME * * ]4 = RWTS TRACK * * ]5 = RWTS SECTOR * * ]6 = RWTS BUFFER * * ]7 = RWTS COMMAND * * * * CYCLES: 228+ * * SIZE: 141 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * SRWTS MAC LDA ]1 ; {4C3B} RWTS SLOT STA MSLOT ; {4C3B} LDA ]2 ; {4C3B} RWTS DRIVE STA MDRIVE ; {4C3B} LDA ]3 ; {4C3B} RWTS VOLUME STA MVOL ; {4C3B} LDA ]4 ; {4C3B} RWTS TRACK STA MTRACK ; {4C3B} LDA ]5 ; {4C3B} RWTS SECTOR STA MSECTOR ; {4C3B} IF #=]6 ; IF VALUE IS A LITERAL LDA ]6 ; {4C3B} THEN STORE LITERAL STA MBUFFER ; {4C3B} LOW AND HIGH BYTES LDA ]6/$100 ; {4C3B} STA MBUFFER+1 ; {4C3B} ELSE ; OTHERWISE, LDA ]6 ; {4C3B} LOAD VALUE FROM ADDRESS STA MBUFFER ; {4C3B} AND STORE IN BUFFER LDA ]6+1 ; {4C3B} ADDRESS POINTER STA MBUFFER+1 ; {4C3B} FIN LDA ]7 ; {4C3B} RWTS COMMAND STA MCMD ; {4C3B} JSR _SETRWTS ; {148C81B} SET THE PARAMETERS <<< * ``` --- ### THE GRWTS MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------- | | Name | `GRWTS` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Run the DOS RWTS Routine. | | Input | none | | Output | none | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 19+ | | Bytes | 11 | | Notes | none | | See Also | `SRWTS` | --- *DETAILS* The `GRWTS` macro simply runs the **RWTS** routine found in DOS. At the very least, the `SRWTS` macro should be called beforehand to set the various parameters used by **RWTS**. `LISTING 6.22: MAC.DOSREQ.ASM GRWTS Macro Source` ```assembly * *``````````````````````````````* * GRWTS * * * * RUN THE RWTS ROUTINE. * * * * PARAMETERS * * * * NONE. * * * * CYCLES: 19+ * * SIZE: 11 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * GRWTS MAC JSR ]LOCRPL ; {6C3B} (GET ]LOCRPL CYCLES/SIZE) JSR ]RWTS ; {6C3B} (GET CYCLES/SIZE) LDA #0 ; {3C2B} STA $48 ; {4C3B} FIX P REG FOR DOS <<< * ``` --- ### THE FMFIL MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FMFIL` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Fill the most common parameters in the FPL. | | Input | ]1 = Command
]2 = Slot
]3 = Drive
]4 = Volume
]5 = Record Number | | Output | none | | Dependencies | `_FMGETPARM` `_FMBUFFSCAN` `_SETPBUFFS` `_FMPSET` `_FMPSETA` | | Flags Destroyed | NZCV | | Cycles | 603+ | | Bytes | 303 | | Notes | none | | See Also | `SRWTS` `FMNAM` | --- *DETAILS* The `FMFIL` macro fills out the most common parameters used in the **File Parameter List (FPL)**. This includes the file command, slot, drive, volume, and record number. Note that not all of these are applicable to every use. Like with `SRWTS`, the volume can be set to **#0** to indicate that any volume is acceptable. `LISTING 6.23: MAC.DOSREQ.ASM FMFIL Macro Source` ```assembly * *``````````````````````````````* * FMFIL (NATHAN RIGGS) * * * * FILLS THE MOST COMMON AREAS * * IN THE FILE PARAMETERS. THIS * * INCLUDES THE COMMAND, SLOT, * * DISK, VOLUME AND RECORD. * * * * PARAMETERS * * * * ]1 = COMMAND * * ]2 = SLOT * * ]3 = DRIVE * * ]4 = VOLUME (0 FOR ANY) * * ]5 = RECORD NUMBER * * * * CYCLES: 603+ * * SIZE: 303 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FMFIL MAC JSR _FMGETPARM ; {26C13B} GET FILE PARAMS ADDRESS JSR _FMBUFFSCAN ; {217C120B} SCAN FOR FREE FILE BUFF JSR _SETPBUFFS ; {125C67B} SET PARAMETER BUFFERS LDA ]1 ; {4C3B} COMMAND TO PARAMETERS LDY #]P_CMD ; {3C2B} SET INDEX TO COMMAND OFFSET JSR _FMPSET ; {36C19B} SET COMMAND LDA ]2 ; {4C3B} SLOT TO PARAMETERS LDY #]P_SLOT ; {3C2B} SET INDEX TO SLOT OFFSET JSR _FMPSET ; {36C19B} SET SLOT ; VOLUME AND RECORD NUMBER LDA ]3 ; {4C3B} DRIVE TO PARAMETERS LDY #]P_DRV ; {3C2B} SET INDEX TO DRIVE OFFSET JSR _FMPSET ; {36C19B} SET DRIVE LDA ]4 ; {4C3B} VOLUME TO PARAMS, 0 FOR ANY LDY #]P_VOL ; {3C2B} SET INDEX TO VOLUME OFFSET JSR _FMPSET ; {36C19B} SET VOLUME _AXLIT ]5 ; {8C6B} LDY #]P_REC ; {3C2B} SET INDEX TO RECORD OFFSET JSR _FMPSETA ; {52C29B} SET RECORD LOW AND HIGH <<< * ``` --- ### THE FMNAM MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FMNAM` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Copy a string with a preceding length-byte to the filename buffer. | | Input | ]1 = Source string address | | Output | none | | Dependencies | `_NAMESTR` `_FN2BUFF` | | Flags Destroyed | NZCV | | Cycles | 117+ | | Bytes | 70 | | Notes | none | | See Also | `FMFIL` | --- *DETAILS* The `FMNAM` macro copies a string with a preceding length-byte into a 30-byte memory location, filling the unused bytes in the destination with spaces. This is then copied to the **Filename Buffer** in a currently used file buffer. This filename is used for commands such as deletion, verification, opening and closing, and so on. This is also used with the renaming command, with the addition of a destination filename. `LISTING 6.24: MAC.DOSREQ.ASM FMNAM Macro Source` ```assembly * *``````````````````````````````* * FMNAM (NATHAN RIGGS) * * * * COPY A STRING HOLDING THE * * NAME OF A FILE BEING HANDLED * * TO A 30-BYTE LOCATION FILLED * * WITH SPACES, THEN COPY THAT * * TO THE FILE PARAMETER LIST. * * * * PARAMETERS * * * * ]1 = ADDRESS OF STRING * * * * CYCLES: 117+ * * SIZE: 70 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FMNAM MAC _AXLIT ]1 JSR _NAMESTR ; {70C45B} COPY STRING TO TEMP BUFF JSR _FN2BUFF ; {47C25B} COPY TEMP BUFF TO FNAME BUFF <<< * ``` --- ### THE FRWB MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FRWB` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Read or write a byte in a file. | | Input | ]1 = Read/Write flag
]2 = Command
]3 = Slot
]4 = Drive
]5 = Volume
]6 = Record Number
]7 = Byte offset
]8 = Byte to write, if writing | | Output | none | | Dependencies | `FMFIL` `_FMPSET` `_FMPSETA` | | Flags Destroyed | NZCV | | Cycles | 779+ | | Bytes | 404 | | Notes | none | | See Also | `FWRTB` `FRDB` `FRWR` `FRDR` `FWRTR` | --- *DETAILS* The `FRWB` Macro either reads or writes a single byte in an open file, depending on which flag is provided the macro in the first parameter. Usually, this macro is used internally, rather than by the end user; the `FWRTB` macro and the `FRDB` macro are used instead to write and read a byte in a file. If writing, the eighth parameter is set to the byte to write; if not, this parameter is ignored. It should also be noted that this macro does not return a value when reading a byte; instead, this is handled by the `FRDB` macro, as the byte is returned by the file manager in the **File Parameter List (FPL)**. As usual, a **#0** value can be passed to the volume parameter to indicate that any volume is acceptable. `LISTING 6.25: MAC.DOSREQ.ASM FRWB Macro Source` ```assembly * *``````````````````````````````* * FRWB (NATHAN RIGGS) * * * * EITHER READ OR WRITE A BYTE. * * THIS USUALLY ISN'T CALLED * * DIRECTLY, BUT THROUGH * * ANOTHER MACRO. * * * * PARAMETERS * * * * ]1 = READ/WRITE FLAG (#3/4) * * ]2 = COMMAND * * ]3 = SLOT * * ]4 = DRIVE * * ]5 = VOLUME (0 FOR ANY) * * ]6 = RECORD NUMBER * * ]7 = BYTE OFFSET * * ]8 = BYTE TO WRITE (0 READ) * * * * CYCLES: 779+ * * SIZE: 404 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FRWB MAC * FMFIL ]2;]3;]4;]5;]6 ; {603C303B} * LDA ]1 ; {4C3B} READ OR WRITE FLAG LDY #]P_RDWR ; {3C2B} INDEX TO READ/WRITE FLAG JSR _FMPSET ; {30C16B} SET THE READ/WRITE FLAG LDA #]SC_PRWB ; {3C2B} SET POS THEN READ OR WRITE LDY #]P_SUBC ; {3C2B} SET INDEX TO SUBCODE OFFSET JSR _FMPSET ; {30C16B} SET THE SUBCODE _AXLIT ]7 ; {8C6B} LDY #]P_BOFF ; {3C2B} INDEX TO BYTE OFFSET JSR _FMPSETA ; {46C26B} SET TWO BYTE OFFSET VALUE LDA ]8 ; {4C3B} BYTE TO WRITE, IF WRITING LDY #]P_BYTE ; {3C2B} WRITE BYTE JSR _FMPSET ; {30C16B} SET BYTE LDX #1 ; {3C2B} DON'T CREATE NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER <<< * ``` --- ### THE FWRTB MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FWRTB` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Write a byte to a file. | | Input | ]1 = Slot
]2 = Drive
]3 = Volume
]4 = Record number
]5 = Byte offset
]6 = Byte to write | | Output | none | | Dependencies | `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 665+ | | Bytes | 337 | | Notes | none | | See Also | `FRWB` `FRDB` `FRWR` `FRDR` `FWRTR` `FOPEN` `FCLOS` | --- *DETAILS* The `FWRTB` macro is used for writing a single byte at a time to an open file. Like with most File Manager operations, a value of **#0** placed in the volume parameter indicates that any volume is acceptable. Records in files work much the same way as they do in Applesoft BASIC: each record in a file is separated by a carriage return (**#$8D**), with the zeroth record being the first string of text prior to the first carriage return. These are usually used with text files, which are only marginally supported by the DOS collection: binary files make much more sense to use in Assembly, even when the data itself represents text characters. This is not to say that text files cannot be used--the `FOPEN` macro allows you to read and write text files--but that it is better for the end programmer to devise his or her own system for dealing with text files, as there is no standard method for recognizing an End-of-File (EOF) marker. Both binary files and text files can be fully read into memory before being parsed by a given routine. The byte offset is particularly useful with `FWRTB`, as without it only the first byte of the file could be written. A byte counter can be used to read or write each consecutive byte at a time, passing the counter value via the offset. The `FOPEN` macro should be called before `FWRTB`, and the `FCLOS` macro should be called when all operations on the file are finished. `LISTING 6.26: MAC.DOSREQ.ASM FWRTB Macro Source` ```assembly * *``````````````````````````````* * FWRTB (NATHAN RIGGS) * * * * WRITE A BYTE TO A FILE. * * * * PARAMETERS * * * * ]1 = SLOT * * ]2 = DRIVE * * ]3 = VOLUME * * ]4 = RECORD NUMBER * * ]5 = BYTE OFFSET * * ]6 = BYTE TO WRITE (0 READ) * * * * CYCLES: 665+ * * SIZE: 337 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FWRTB MAC * ** FRWB ARGUMENTS ** ** ]1 = READ OR WRITE CODE (3 = READ, 4 = WRITE) ** ]2 = READ OR WRITE COMMAND ** ]3 = SLOT ** ]4 = DRIVE ** ]5 = VOLUME (0 FOR ANY) ** ]6 = RECORD NUMBER ** ]7 = BYTE OFFSET ** ]8 = BYTE TO WRITE, IF WRITING * FRWB #4;#]FC_WRIT;]1;]2;]3;]4;]5;]6 ; {603C303B} * LDY #]P_RETC ; {3C2B} INDEX TO RETURN CODE OFFSET JSR _FMPGET ; {26C14B} GET THE RETURN CODE TAX ; {2C1B} PASS BACK IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFFER FOR USE <<< * ``` --- ### THE FRDB MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FRDB` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Read a byte from a file. | | Input | ]1 = Slot
]2 = Drive
]3 = Volume
]4 = Record number
]5 = Byte offset
]6 = Byte to write (always 0) | | Output | none | | Dependencies | `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 700+ | | Bytes | 357 | | Notes | none | | See Also | `FRWB` `FWRTB` `FRWR` `FRDR` `FWRTR` | --- *DETAILS* The `FRDB` macro reads a byte from an open file and returns the byte in the **.A** register. If the volume is set to **#0**, any volume will be accepted. Records in files work much the same way as they do in Applesoft BASIC: each record in a file is separated by a carriage return (**#$8D**), with the zeroth record being the first string of text prior to the first carriage return. These are usually used with text files, which are only marginally supported by the DOS collection: binary files make much more sense to use in Assembly, even when the data itself represents text characters. This is not to say that text files cannot be used--the `FOPEN` macro allows you to read and write text files--but that it is better for the end programmer to devise his or her own system for dealing with text files, as there is no standard method for recognizing an End-of-File (EOF) marker. Both binary files and text files can be fully read into memory before being parsed by a given routine. The byte offset is particularly useful with `FRDB`, as without it only the first byte of the file could be read. A byte counter can be used to read or write each consecutive byte at a time, passing the counter value via the offset. The `FOPEN` macro should be called before `FWRTB`, and the `FCLOS` macro should be called when all operations on the file are finished. `LISTING 6.27: MAC.DOSREQ.ASM FRDB Macro Source` ```assembly * *``````````````````````````````* * FRDB (NATHAN RIGGS) * * * * READ A BYTE FROM A FILE. * * * * PARAMETERS * * * * ]1 = SLOT * * ]2 = DRIVE * * ]3 = VOLUME * * ]4 = RECORD NUMBER * * ]5 = BYTE OFFSET * * ]6 = BYTE TO WRITE (0 READ) * * * * CYCLES: 700+ * * SIZE: 357 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FRDB MAC * ** FWRB ARGUMENTS ** ** ]1 = READ OR WRITE CODE (3 = READ, 4 = WRITE) ** ]2 = READ OR WRITE COMMAND ** ]3 = SLOT ** ]4 = DRIVE ** ]5 = VOLUME (0 FOR ANY) ** ]6 = RECORD NUMBER ** ]7 = BYTE OFFSET ** ]8 = BYTE TO WRITE, IF WRITING * FRWB #3;#]FC_READ;]1;]2;]3;]4;]5;]6 ; {603C303B} * LDY #]P_BYTE ; {3C2B} INDEX TO BYTE TO READ JSR _FMPGET ; {26C14B} GET BYTE IN THE PARAMETERS STA BPAR1 ; {3C2B} HOLD IN ZERO PAGE LDY #]P_RETC ; {3C2B} INDEX TO THE RETURN CODE OFFSET JSR _FMPGET ; {26C14B} GET THE RETURN CODE TAX ; {2C1B} PASS BACK IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFFER FOR USE LDA BPAR1 ; {3C2B} PASS READ BYTE IN .A <<< * ``` --- ### THE FRWR MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FRWR` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Read or write a range of bytes in a file. | | Input | ]1 = READ/WRITE flag
]2 = Command
]3 = Slot
]4 = Drive
]5 = Volume
]6 = Record number
]7 = Byte offset
]8 = Range Address
]TEMP = Range length | | Output | none | | Dependencies | `_FMPSET` `_FMPSETA` | | Flags Destroyed | NZCV | | Cycles | 846+ | | Bytes | 451 | | Notes | none | | See Also | `FRWB` `FWRTB` `FRDB` `FRDR` `FWRTR` | --- *DETAILS* The `FRWR` macro reads or writes a range of bytes from or to an open file, with the Range Address either containing the bytes to be written up to the specified length or the memory area to store the bytes read from the file at the given length. It is notable that because **Merlin 8 Pro** can only handle eight built-in variables (]1 - ]8), the ]TEMP variable is used to pass the range length. Additionally, and like usual, a value of **#0** in the volume parameter indicates that any volume number is valid. For the most part, this macro is meant to be used internally. The end user should use the `FRDR` macro for reading a range of bytes and the `FWRTR` macro for writing a range of bytes. `LISTING 6.28: MAC.DOSREQ.ASM FRWR Macro Source` ```assembly * *``````````````````````````````* * FRWR (NATHAN RIGGS) * * * * READ OR WRITE A RANGE. * * * * PARAMETERS * * * * ]1 = READ/WRITE FLAG * * ]2 = COMMAND * * ]3 = SLOT * * ]4 = DRIVE * * ]5 = VOLUME * * ]6 = RECORD NUMBER * * ]7 = BYTE OFFSET * * ]8 = RANGE ADDRESS * * ]TEMP = RANGE LENGTH * * * * CYCLES: 846+ * * SIZE: 451 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FRWR MAC * ** SET THE COMMAND, SLOT, DRIVE, VOLUME AND RECORD NUMBER * FMFIL ]2;]3;]4;]5;]6 ; {603C303B} * LDA ]1 ; {4C3B} LOAD READ OR WRITE FLAG LDY #]P_RDWR ; {3C2B} INDEX TO RD/WRT FLAG OFFSET JSR _FMPSET ; {30C16B} SET READ OR WRITE FLAG LDA #]SC_PRWR ; {3C2B} SUBCODE FOR POS AND READ/WRITE LDY #]P_SUBC ; {3C2B} INDEX TO SUBCODE OFFSET JSR _FMPSET ; {30C16B} SET SUBCODE _AXLIT ]7 ; {8C6B} LDY #]P_BOFF ; {3C2B} INDEX TO BYTE OFFSET JSR _FMPSETA ; {46C26B} SET BYTE OFFSET _AXLIT ]8 ; {8C6B} LDY #]P_RADDR ; {3C2B} INDEX TO RANGE ADDR OFFSET JSR _FMPSETA ; {46C26B} SET RANGE ADDRESS LDA ]TEMP ; {4C3B} GET RANGE LENGTH LDX ]TEMP+1 ; {4C3B} LOW BYTE AND HIGH BYTE LDY #]P_RLEN ; {3C2B} INDEX TO RANGE LENGTH OFFSET JSR _FMPSETA ; {46C26B} SET RANGE LENGTH LDX #1 ; {3C2B} DON'T CREATE NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER <<< * ``` --- ### THE FRDR MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FRDR` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Read a range of bytes from a file. | | Input | ]1 = Slot
]2 = Drive
]3 = Volume
]4 = Record number
]5 = Byte offset
]6 = Range address
]7 = Range length | | Output | none | | Dependencies | `_FMPGET` `FRWR` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 697+ | | Bytes | 361 | | Notes | none | | See Also | `FRWB` `FWRTB` `FRDB` `FRWR` `FWRTR` | --- *DETAILS* The `FRDR` macro reads a range of bytes from an open file, storing the range starting at the given range address through to the given range length (two bytes). As per the collection standard, a value of **#0** in the volume parameter indicates that any volume number is valid. Records in files work much the same way as they do in Applesoft BASIC: each record in a file is separated by a carriage return (**#$8D**), with the zeroth record being the first string of text prior to the first carriage return. These are usually used with text files, which are only marginally supported by the DOS collection: binary files make much more sense to use in Assembly, even when the data itself represents text characters. This is not to say that text files cannot be used--the `FOPEN` macro allows you to read and write text files--but that it is better for the end programmer to devise his or her own system for dealing with text files, as there is no standard method for recognizing an End-of-File (EOF) marker. Both binary files and text files can be fully read into memory before being parsed by a given routine. The byte offset is used to start reading or writing the range at a particular location in the file. The `FOPEN` macro should be called before `FRDR`, and the `FCLOS` macro should be called when all operations on the file are finished. `LISTING 6.29: MAC.DOSREQ.ASM FRDR Macro Source` ```assembly * *``````````````````````````````* * FRDR (NATHAN RIGGS) * * * * READ A RANGE FROM A FILE. * * * * PARAMETERS * * * * ]1 = SLOT * * ]2 = DRIVE * * ]3 = VOLUME * * ]4 = RECORD NUMBER * * ]5 = BYTE OFFSET * * ]6 = RANGE ADDRESS * * ]7 = RANGE LENGTH * * * * CYCLES: 697+ * * SIZE: 361 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FRDR MAC IF #=]7 ; IF RANGE ADDR IS A LITERAL LDA ]7/$100 ; {4C3B} THEN LOAD HIGH BYTE STA ]TEMP+1 ; {4C3B} AND STORE LDA ]7 ; {4C3B} AND LOAD LOW BYTE STA ]TEMP ; {4C3B} AND STORE IN TEMP ELSE LDA ]7+1 ; {4C3B} LOAD HIGH BYTE STA ]TEMP+1 ; {4C3B} STORE HIGH BYTE LDA ]7 ; {4C3B} LOAD LOW BYTE STA ]TEMP ; {4C3B} STORE LOW BYTE FIN * FRWR #3;#]FC_READ;]1;]2;]3;]4;]5;]6 ; {603C303B} * LDY #]P_RETC ; {3C2B} INDEX TO RETURN CODE JSR _FMPGET ; {26C14B} GET RETURN CODE TAX ; {2C1B} HOLD IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFFER FOR USE <<< * ``` --- ### THE FWRTR MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FWRTR` | | Type | Macro | | File | `MAC.DOSREQ.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Write a range of bytes to a file. | | Input | ]1 = Slot
]2 = Drive
]3 = Volume
]4 = Record number
]5 = Byte offset
]6 = Range address
]7 = Range length | | Output | none | | Dependencies | `_FMPGET` `FRWR` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 940+ | | Bytes | 509 | | Notes | none | | See Also | `FRWB` `FWRTB` `FRDB` `FRWR` `FRDR` | --- *DETAILS* The `FWRTR` macro writes to an open file a range of bytes found at a given starting range address through a given range length. As per the collection standard, a value of #0 in the volume parameter indicates that any volume number is valid. Records in files work much the same way as they do in Applesoft BASIC: each record in a file is separated by a carriage return (**#$8D**), with the zeroth record being the first string of text prior to the first carriage return. These are usually used with text files, which are only marginally supported by the DOS collection: binary files make much more sense to use in Assembly, even when the data itself represents text characters. This is not to say that text files cannot be used--the `FOPEN` macro allows you to read and write text files--but that it is better for the end programmer to devise his or her own system for dealing with text files, as there is no standard method for recognizing an End-of-File (EOF) marker. Both binary files and text files can be fully read into memory before being parsed by a given routine. The byte offset is used to start reading or writing the range at a particular location in the file. The `FOPEN` macro should be called before `FWRTR`, and the `FCLOS` macro should be called when all operations on the file are finished. `LISTING 6.30: MAC.DOSREQ.ASM FWRTR Macro Source` ```assembly * *``````````````````````````````* * FWRTR (NATHAN RIGGS) * * * * WRITE A RANGE TO A FILE. * * * * PARAMETERS * * * * ]1 = SLOT * * ]2 = DRIVE * * ]3 = VOLUME * * ]4 = RECORD NUMBER * * ]5 = BYTE OFFSET * * ]6 = RANGE ADDRESS * * ]7 = RANGE LENGTH * * * * CYCLES: 940+ * * SIZE: 509 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FWRTR MAC IF #=]7 ; IF RANGE LENGTH IS A LITERAL THEN LDA ]7/$100 ; {4C3B} LOAD HIGH BYTE STA ]TEMP+1 ; {4C3B} AND STORE IN TEMP LDA ]7 ; {4C3B} LOAD LOW BYTE STA ]TEMP ; {4C3B} AND STORE IN TEMP ELSE ; OTHERWISE LDA ]7+1 ; {4C3B} LOAD HIGH BYTE STA ]TEMP+1 ; {4C3B} AND STORE IN TEMP LDA ]7 ; {4C3B} LOAD LOW BYTE STA ]TEMP ; {4C3B} AND STORE IN TEMP FIN * FRWR #4;#]FC_WRIT;]1;]2;]3;]4;]5;]6 ; {846C451B} * LDY #]P_RETC ; {3C2B} INDEX TO RETURN CODE JSR _FMPGET ; {26C14B} GET RETURN CODE TAX ; {2C1B} PASS BACK IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFFER FOR USE <<< * ``` --- ## DOS File Manager Macros The MAC.DOSFM.ASM file contains various macros that are used for most file operations. Currently, this includes disk cataloging, locking and unlocking files, deleting files, verifying files, opening and closing files, reading and writing files (both text and binary), renaming files, and bloading and bsaving binary files. Additionally, subroutines are provided for using DOS's **RWTS** routine for low-level access to a disk, though this is mostly limited to reading and writing bytes in a given track and sector. It should be noted that all of these macros need to have both the HEAD.DOS.ASM file and the MAC.DOSREQ.ASM file included (PUT and USE, respectively) in order to function properly (or, rather, at all). `LISTING 6.40: MAC.DOSFM.ASM Heading Source` ```assembly * *``````````````````````````````* * MAC.DOSFM.ASM * * * * THIS FILE CONTAINS MACROS * * USED TO INTERFACE TO THE DOS * * FILE MANAGER. NOTE THE * * FOLLOWING: * * * * 1) THIS COLLECTION CURRENTLY * * HAS A LOT OF OVERHEAD DUE TO * * THE TIGHTLY INTEGRATED * * NATURE OF THE FILE MANAGER. * * * * 2) THIS COLLECTION IS THE * * ONLY ONE IN THE LIBRARY THAT * * ALLOWS FOR USING THE MACROS * * WITHIN THE SUBROUTINES, SAVE * * FOR THE REQUIRED COLLECTION. * * THIS IS TO MAKE EACH OF THE * * SUBROUTINES MORE LEGIBLE, AS * * JUST THE ACT OF PASSING * * VARIABLES TO OTHER ROUTINES * * CAN TAKE UP A SIGNIFICANT * * NUMBER OF BYTES. * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * DATE: 20-APR-2021 * * ASSEMBLER: MERLIN 8 PRO * * OS: DOS 3.3 * * * * SUBROUTINE FILES USED * * * * * * LIST OF MACROS * * * * FCAT : CATALOG * * FULCK : UNLOCK FILE * * FLOCK : LOCK FILE * * FDEL : DELETE FILE * * FVFY : VERIFY FILE * * FCLOS : CLOSE FILE * * FRENM : RENAME FILE * * FOPEN : OPEN FILE * * BLOAD : LOAD BINARY FILE * * BSAVE : SAVE BINARY FILE * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ``` --- ### THE FCAT MACRO _SUMMARY_ | Condition | Value | | --------------- | -------------------------------- | | Name | `FCAT` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Catalog the disk. | | Input | ]1 = Slot
]2 = Drive | | Output | A disk catalog to the screen. | | Dependencies | `_FMFIL` `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 657+ | | Bytes | 348 | | Notes | none | | See Also | none | --- *DETAILS* The `FCAT` macro simply requests a disk catalog to be printed to the text screen. This macro does not provide any way to manipulate the data present in the **Volume Table of Contents (VTOC)**; this feature will be added as a separate macro in later revisions of the collection. `LISTING 6.41: MAC.DOSFM.ASM FCAT Macro Source` ```assembly * *``````````````````````````````* * FCAT (NATHAN RIGGS) * * * * SIMPLY LIST THE DISK CATALOG * * TO THE SCREEN. * * * * PARAMETERS * * * * ]1 = SLOT * * ]2 = DRIVE * * * * CYCLES: 657+ * * SIZE: 348 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FCAT MAC * FMFIL #]FC_CAT;]1;]2;#0;#0 ; {603C303B} SET CMD SLOT DRIVE * LDX #1 ; {3C2B} DON'T CREATE NEW FILE JSR ]FMRUN ; {6C3B} RUN THE FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE JSR _FMPGET ; {32C17B} GET RETURN CODE FROM PARAMS TAX ; {2C1B} HOLD CODE IN .X JSR _BUFFCLEAR ; {37C20B} CLEAR THE FILE BUFF FOR USE <<< * ``` --- ### THE FULCK MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------------------------------------- | | Name | `FULCK` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Unlock a file. | | Input | ]1 = Filename address
]2 = Slot
]3 = Drive | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 629+ | | Bytes | 353 | | Notes | none | | See Also | `FLOCK` | --- *DETAILS* The `FULCK` macro unlocks a file with the specified filename. `LISTING 6.42: MAC.DOSFM.ASM FULCK Macro Source` ```assembly * *``````````````````````````````* * FULCK (NATHAN RIGGS) * * * * UNLOCK A FILE. * * * * PARAMETERS * * * * ]1 = FILENAME STR ADDRESS * * ]2 = SLOT * * ]3 = DRIVE * * * * CYCLES: 629+ * * SIZE: 353 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FULCK MAC * FMFIL #]FC_UNLK;]2;]3;#0;#0 ; {603C303B} * FMNAM ]1 ; {4C3B} SET FILENAME LDX #1 ; {4C3B} DON'T CREATE A NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER LDY #]P_RETC ; {4C3B} SET INDEX TO RETURN CODE JSR _FMPGET ; {32C17B} GET RETURN CODE FROM PARAMS TAX ; {2C1B} HOLD IN .X JSR _BUFFCLEAR ; {37C20B} CLEAR FILE BUFF FOR USE <<< * ``` --- ### THE FLOCK MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------------------------------------- | | Name | `FLOCK` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Lock a file. | | Input | ]1 = Filename address
]2 = Slot
]3 = Drive | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 172+ | | Bytes | 116 | | Notes | none | | See Also | `FULCK` | --- *DETAILS* The `FLOCK` macro locks a file with the specified filename. `LISTING 6.43: MAC.DOSFM.ASM FLOCK Macro Source` ```assembly * *``````````````````````````````* * FLOCK (NATHAN RIGGS) * * * * LOCK A FILE. * * * * PARAMETERS * * * * ]1 = FILENAME STR ADDRESS * * ]2 = SLOT * * ]3 = DRIVE * * * * CYCLES: 172+ * * SIZE: 116 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FLOCK MAC * * FMFIL #]FC_LOCK;]2;]3;#0;#0 ; {603C303B} * FMNAM ]1 ; {117C70B} SET FILENAME LDX #1 ; {4C3B} DON'T CREATE A NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE JSR _FMPGET ; {32C17B} GET RETURN CODE FROM PARAMS TAX ; {2C1B} HOLD IN .X JSR _BUFFCLEAR ; {37C20B} CLEAR FILE BUFF FOR USE <<< * ``` --- ### THE FDEL MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------------------------------------- | | Name | `FDEL` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Delete a file. | | Input | ]1 = Filename address
]2 = Slot
]3 = Drive | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 791+ | | Bytes | 412 | | Notes | none | | See Also | none | --- *DETAILS* The `FDEL` macro deletes a file with the specified filename. `LISTING 6.44: MAC.DOSFM.ASM FDEL Macro Source` ```assembly * *``````````````````````````````* * FDEL (NATHAN RIGGS) * * * * DELETE A FILE. * * * * PARAMETERS * * * * ]1 = FILENAME STR ADDRESS * * ]2 = SLOT * * ]3 = DRIVE * * * * CYCLES: 791+ * * SIZE: 412 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FDEL MAC * FMFIL #]FC_DEL;]2;]3;#0;#0 ; {603C303B} * FMNAM ]1 ; {117C70B} SET FILE NAME LDX #1 ; {3C2B} DON'T CREATE NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE JSR _FMPGET ; {26C14B} GET CODE FROM PARAMS TAX ; {2C1B} HOLD IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFF FOR USE <<< * ``` --- ### THE FVFY MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------------------------------------- | | Name | `FVFY` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Verify a file. | | Input | ]1 = Filename address
]2 = Slot
]3 = Drive | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 791+ | | Bytes | 411 | | Notes | none | | See Also | none | --- *DETAILS* The `FVFY` macro verifies a file with the specified filename. `LISTING 6.45: MAC.DOSFM.ASM FVFY Macro Source` ```assembly * *``````````````````````````````* * FVFY (NATHAN RIGGS) * * * * VERIFY A FILE. * * * * PARAMETERS * * * * ]1 = FILENAME STR ADDRESS * * ]2 = SLOT * * ]3 = DRIVE * * * * CYCLES: 791+ * * SIZE: 411 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FVFY MAC * FMFIL #]FC_VFY;]2;]3;#0;#0 ; {603C303B} * FMNAM ]1 ; {117C70B} SET FILE NAME LDX #1 ; {3C2B} DON'T CREATE A NEW FILE JSR ]FMRUN ; {6C3B} RUN THE FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE JSR _FMPGET ; {26C14B} GET CODE FROM PARAMETERS TAX ; {2C1B} HOLD IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFF FOR USE <<< * ``` --- ### THE FCLOS MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------------------------------------- | | Name | `FCLOS` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Close a file. | | Input | ]1 = Filename address
]2 = Slot
]3 = Drive | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` | | Flags Destroyed | NZCV | | Cycles | 797+ | | Bytes | 415 | | Notes | none | | See Also | none | --- *DETAILS* The `FCLOS` macro closes a file with the specified filename. `LISTING 6.46: MAC.DOSFM.ASM FCLOS Macro Source` ```assembly * *``````````````````````````````* * FCLOS (NATHAN RIGGS) * * * * CLOSE A FILE. * * * * PARAMETERS * * * * ]1 = FILENAME STR ADDRESS * * ]2 = SLOT * * ]3 = DRIVE * * * * CYCLES: 797+ * * SIZE: 415 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FCLOS MAC * FMFIL #]FC_CLOS;]2;]3;#0;#0 ; {603C303B} * FMNAM ]1 ; {117C70B} SET FILENAME LDX #1 ; {3C2B} DON'T CREATE NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE JSR _FMPGET ; {32C17B} GET RETURN CODE TAX ; {2C1B} AND HOLD IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFF FOR USE <<< * ``` --- ### THE FRENM MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FRENM` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Rename a file. | | Input | ]1 = Filename address
]2 = New filename address
]3 = Slot
]4 = Drive | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` `_FMNM2` | | Flags Destroyed | NZCV | | Cycles | 927+ | | Bytes | 578 | | Notes | none | | See Also | none | --- *DETAILS* The `FRENM` macro renames a file with the filename given in the first parameter to the filename given in the second parameter. `LISTING 6.47: MAC.DOSFM.ASM FRENM Macro Source` ```assembly * *``````````````````````````````* * FRENM (NATHAN RIGGS) * * * * RENAME A FILE. * * * * PARAMETER * * * * ]1 = FILENAME STR ADDRESS * * ]2 = NEW NAME STR ADDRESS * * ]3 = SLOT * * ]4 = DRIVE * * * * CYCLES: 927+ * * SIZE: 578 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FRENM MAC * FMFIL #]FC_REN;]3;]4;#0;#0 ; {603C303B} * FMNAM ]1 ; {117C70B} SET FILENAME _AXLIT ]2 ; {8C6B} JSR _NAMESTR2 ; {64C42B} COPY TO 2ND FILENAME BUFF JSR _FMNM2 ; {64C42B} SET ADDRESS IN PARAMS LDX #1 ; {3C2B} DON'T CREATE NEW FILE JSR ]FMRUN ; {6C3B} RUN FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE JSR _FMPGET ; {26C14B} GET RETURN CODE TAX ; {2C1B} AND HOLD IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFFER FOR USE <<< * ``` --- ### THE FOPEN MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FOPEN` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Open a file. | | Input | ]1 = Filename address
]2 = Slot
]3 = Drive
]4 = Volume
]5 = Record
]6 = File type | | Output | none. | | Dependencies | `_FMFIL` `FMNAM` `_FMPGET` `_BUFFCLEAR` `_FMPSET` | | Flags Destroyed | NZCV | | Cycles | 828+ | | Bytes | 433 | | Notes | none | | See Also | `FCLOS` | --- *DETAILS* The `FOPEN` macro opens a file for reading or writing, which is determined by the `FRDB`, `FWRTB`, `FRDR` and `FWRTR` macros. Beyond opening the file for use, `FOPEN` determines the type of file that will be read or written to. The following table describes which type of file corresponds to the value passed in parameter number six, along with a variable name to be used in place of a number for ease of use: | Value | Variable Name | File Type | |----------|-----------------------|--------------| |$00| TYP_TXT | Text File | |$01| TYP_INT | Integer BASIC File | |$02| TYP_APP | Applesoft BASIC File | |$04| TYP_BIN | Binary File | |$08| TYP_REL | Relocatable File | |$10| TYP_S | S Type File | |$20| TYP_A | A Type File | |$40| TYP_B | B Type File | `LISTING 6.48: MAC.DOSFM.ASM FOPEN Macro Source` ```assembly * *``````````````````````````````* * FOPEN (NATHAN RIGGS) * * * * OPEN FILE FOR READ OR WRITE. * * * * PARAMETERS * * * * ]1 = FILENAME STR ADDRESS * * ]2 = SLOT * * ]3 = DRIVE * * ]4 = VOLUME (0 FOR ANY) * * ]5 = RECORD NUMBER * * ]6 = FILE TYPE * * * * CYCLES: 828+ * * SIZE: 433 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * FOPEN MAC * FMFIL #]FC_OPEN;]2;]3;]4;]5 ; {603C303B} * LDA ]6 ; {4C3B} FILE TYPE IF NEW FILE LDY #]P_TYPE ; {3C2B} SET TYPE FOR WRITING JSR _FMPSET ; {30C16B} FMNAM ]1 ; {117C70B} SET THE FILENAME LDX #0 ; {3C2B} NEW FILE ON OPEN JSR ]FMRUN ; {6C3B} RUN FILE MANAGER LDY #]P_RETC ; {3C2B} SET INDEX TO RETURN CODE OFFSET JSR _FMPGET ; {26C14B} GET RETURN CODE TAX ; {2C1B} HOLD IT IN .X JSR _BUFFCLEAR ; {31C17B} CLEAR FILE BUFFER FOR USE <<< * ``` --- ### THE BLOAD MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `BLOAD` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Binary-load a file. | | Input | ]1 = Filename address
]2 = Loading address
]3 = Slot
]4 = Drive
]5 = Volume | | Output | none. | | Dependencies | `FBLOAD` | | Flags Destroyed | NZCV | | Cycles | 3768+ | | Bytes | 2735 | | Notes | none | | See Also | `BSAVE` `FBSAVE` `FBLOAD` | --- *DETAILS* The `BLOAD` macro loads the contents of a binary file into memory either at a specified address or, if the address passed is **#$0000**, at the address stored in the start of the file. Like with all properly saved binary file, both the default address and the file byte-length is stored in the first four bytes of the file; these are not copied to the specified location. The length is passed back to the calling program via the **.A** register (low) and **.X** register (high). `LISTING 6.49: MAC.DOSFM.ASM BLOAD Macro Source` ```assembly * *``````````````````````````````* * BLOAD (NATHAN RIGGS) * * * * LOAD A MACHINE LANGUAGE FILE * * INTO MEMORY AT A SPECIFIED * * ADDRESS. IF THE ADDRESS IS * * #0000, THEN USE THE DEFAULT * * ADDRESS PROVIDED AT THE * * START OF THE FILE. THE FILE * * LENGTH IS ALSO HELD AT THE * * BEGINNING OF THE FILE, SO * * THERE IS NO NEED TO PASS IT * * HERE. THIS LENGTH IS PASSED * * BACK TO THE USER VIA THE * * .A (LOW) AND .X (HIGH) * * REGISTERS. * * * * PARAMETERS * * * * ]1 = FILENAME STRING ADDR * * ]2 = LOADING ADDRESS * * ]3 = SLOT * * ]4 = DRIVE * * ]5 = VOLUME * * * * DESTROYS: NZCIDV * * ^^^ ^ * * * * CYCLES: 3768+ * * SIZE: 2735 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * BLOAD MAC _MLIT ]1;WPAR1 ; {16C12B} PARSE STRING ADDRESS _MLIT ]2;WPAR2 ; {16C12B} PARSE LOAD ADDRESS LDA ]3 ; {4C3B} LOAD SLOT STA BPAR1 ; {3C2B} AND STORE ON ZERO LDA ]4 ; {4C3B} LOAD DRIVE STA BPAR2 ; {3C2B} AND STORE ON ZERO LDA ]5 ; {4C3B} LOAD VOLUME STA BPAR3 ; {3C2B} AND STORE ON ZERO JSR FBLOAD ; {3715C2696B} RUN FBLOAD SUBROUTINE <<< * ``` --- ### THE FBLOAD SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FBLOAD` | | Type | Subroutine | | File | `SUB.FBLOAD.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Binary-load a file. | | Input | WPAR1 = Filename string address
WPAR2 = Loading Address
BPAR1 = Slot
BPAR2 = Drive
BPAR3 = Volume | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 3715+ | | Bytes | 2696 | | Notes | none | | See Also | `BSAVE` `FBSAVE` `BLOAD` | --- *DETAILS* The `FBLOAD` subroutine loads a binary file into the designated memory address, with the length being determined by a preceding length-byte in the file. If the memory address passed is **#$0000**, then the default address found in the first two bytes of the file is used in place of the address passed. These first four bytes of the file, signifying the default memory address and the length of the range in bytes, are not copied along with the rest of the file. The length of the data is store in **.A** (low byte) and **.X** (high byte), as well as in `RETURN`. `RETLEN` carries **#$02**. `LISTING 6.50: SUB.FBLOAD.ASM Source` ```assembly * *``````````````````````````````* * FBLOAD (NATHAN RIGGS) * * * * BLOAD A FILE'S MACHINE * * LANGUAGE CONTENTS TO A GIVEN * * MEMORY RANGE. NOTE THAT THE * * FIRST FOUR BYTES OF A BIN * * FILE CONTAINS THE LOADING * * ADDRESS (TWO BYTES) AND THE * * LENGTH OF THE CODE (TWO * * BYTES). IF THE ADDRESS * * EQUALS #0000, THEN THESE * * VALUES WILL BE USED INSTEAD. * * * * INPUT * * * * WPAR1 = FILENAME STR ADDR * * WPAR2 = LOAD ADDRESS * * BPAR1 = SLOT * * BPAR2 = DRIVE * * BPAR3 = VOLUME * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 3715+ * * SIZE: 2696 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ]FNSTR EQU WPAR1 ; FILENAME STRING ]LDADDR EQU WPAR2 ; LOADING ADDRESS ]FLEN EQU WPAR3 ; FILE LENGTH ]SLOT EQU BPAR1 ]DRIVE EQU BPAR2 ]VOL EQU BPAR3 ]FLDADDR EQU ADDR4 ; ADDRESS STORED IN FILE * FBLOAD * ** FIRST, READ FIRST TWO BYTES TO GET THE ** DEFAULT ADDRESS. IF THE ADDRESS PASSED IS ** #0000, THEN THE DEFAULT ADDRESS IS USED INSTEAD. * FOPEN ]FNSTR;]SLOT;]DRIVE;]VOL;#0;#]TYP_BIN ; {828C433B} FRDB ]SLOT;]DRIVE;#0;#0;#0;#0 ; {700C357B} STA ]FLDADDR ; {4C3B} FRDB ]SLOT;]DRIVE;#0;#0;#1;#0 ; {700C357B} STA ]FLDADDR+1 ; {4C3B} * ** NOW GET THE LENGTH OF THE FILE. THEORETICALLY, ** THIS SHOULDN'T INCLUDE THE FIRST 4 BYTES? * FRDB ]SLOT;]DRIVE;#0;#0;#2;#0 ; {700C357B} STA ]FLEN ; {4C3B} FRDB ]SLOT;]DRIVE;#0;#0;#3;#0 ; {700C357B} STA ]FLEN+1 ; {4C3B} * ** IF PASSED ADDRESS IS ZERO, THEN USE THE ** DEFAULT ADDRESS. OTHERWISE, COPY THE PASSED ** ADDRESS INTO THE DEFAULT ADDRESS VARIABLE. * LDA ]LDADDR ; {4C3B} CMP #0 ; {3C2B} BNE :SET ; {3C2B} LDA ]LDADDR+1 ; {4C3B} CMP #0 ; {3C2B} BNE :SET ; {3C2B} JMP :SKIP ; {633B} :SET LDA ]LDADDR ; {4C3B} STA ]FLDADDR ; {4C3B} LDA ]LDADDR+1 ; {4C3B} STA ]FLDADDR+1 ; {4C3B} * ** NOW READ THE RANGE OF THE ENTIRE FILE AND ** STORE IT IN MEMORY AT THE APPROPRIATE LOCATION. * :SKIP FRDR ]SLOT;]DRIVE;#0;#0;#4;]FLDADDR;]FLEN ; {697C361B} FCLOS ]FNSTR;]SLOT;]DRIVE ; {797C415B} * LDA ]FLEN ; {4C3B} LOAD LENGTH LOW BYTE STA RETURN ; {4C3B} AND HOLD IN .A AND RETURN LDX ]FLEN+1 ; {4C3B} LOAD LENGTH HIGH BYTE STA RETURN+1 ; {4C3B} AND HOLD IN .X AND RETURN+1 LDY #2 ; {3C2B} LOAD BYTE LENGTH OF RETURN STY RETLEN ; {4C3B} AND STORE IN RETLEN RTS ; {6C1B} * ``` --- ### THE BSAVE MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `BSAVE` | | Type | Macro | | File | `MAC.DOSFM.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Binary-save a range of memory. | | Input | ]1 = Filename address
]2 = Loading address
]3 = Range length
]4 = Slot
]5 = Drive
]6 = Volume | | Output | none. | | Dependencies | `FBSAVE` | | Flags Destroyed | NZCV | | Cycles | 5300+ | | Bytes | 2758 | | Notes | none | | See Also | `BLOAD` `FBSAVE` `FBLOAD` | --- *DETAILS* The `BSAVE` macro stores a range of memory from a starting address to a given byte-length in a binary file, holding the starting address in the first two bytes of the file and the range length in the third and fourth bytes. This is how all binary files are stored in DOS, or should be stored. `LISTING 6.51: MAC.DOSFM.ASM BSAVE Macro Source` ```assembly * *``````````````````````````````* * BSAVE (NATHAN RIGGS) * * * * STORES A MEMORY RANGE IN A * * FILE STARTING AT THE LOADING * * ADDRESS AND CONTINUING FOR * * THE GIVEN RANGE LENGTH. THE * * FIRST TWO BYTES OF THE FILE * * HOLD THE LOADING ADDRESS, * * AND THE 3RD AND 4TH BYTES * * HOLD THE RANGE LENGTH. * * * * PARAMETERS * * * * ]1 = FILENAME STRING ADDR * * ]2 = LOADING ADDRESS * * ]3 = RANGE LENGTH * * ]4 = SLOT * * ]5 = DRIVE * * ]6 = VOLUME * * * * DESTROYS: NZCIDV * * ^^^ ^ * * * * CYCLES: 5300+ * * SIZE: 2758 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * BSAVE MAC _MLIT ]1;WPAR1 ; {16C12B} PARSE STRING ADDRESS _MLIT ]2;WPAR2 ; {16C12B} PARSE LOAD ADDRESS _MLIT ]3;WPAR3 ; {16C12B} LDA ]4 ; {4C3B} LOAD SLOT STA BPAR1 ; {3C2B} AND STORE ON ZERO LDA ]5 ; {4C3B} LOAD DRIVE STA BPAR2 ; {3C2B} AND STORE ON ZERO LDA ]6 ; {4C3B} LOAD VOLUME STA BPAR3 ; {3C2B} AND STORE ON ZERO JSR FBSAVE ; {5231C2707B} RUN FBLOAD SUBROUTINE <<< * ``` --- ### THE FBSAVE SUBROUTINE _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------------------------------ | | Name | `FBSAVE` | | Type | Subroutine | | File | `SUB.FBSAVE.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Binary-save a file. | | Input | WPAR1 = Filename string address
WPAR2 = Loading Address
WPAR3 = Range length
BPAR1 = Slot
BPAR2 = Drive
BPAR3 = Volume | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 3715+ | | Bytes | 2696 | | Notes | none | | See Also | `BSAVE` `FBLOAD` `BLOAD` | --- *DETAILS* The `FBSAVE` subroutine saves a memory range to a binary file that starts at a given address. The first two bytes of the file holds the starting address, while the next two bytes hold the range length. `LISTING 6.52: SUB.FBSAVE.ASM Source` ```assembly * *``````````````````````````````* * FBSAVE (NATHAN RIGGS) * * * * THIS SUBROUTINE TAKES AN * * ADDRESS AND A BYTE LENGTH, * * THEN SAVES THAT MEMORY RANGE * * TO A FILE. THE FIRST TWO * * BYTES HOLD THE ADDRESS WHERE * * THE MEMORY WAS STORED, AND * * THE THIRD AND FOURTH BYTES * * OF THE FILE HOLD THE LENGTH * * OF THE FILE (NOT INCLUDING * * THE FOUR PRECEDING BYTES). * * * * INPUT * * * * WPAR1 = FILENAME STR ADDR * * WPAR2 = LOAD ADDRESS * * WPAR3 = RANGE LENGTH * * BPAR1 = SLOT * * BPAR2 = DRIVE * * BPAR3 = VOLUME * * * * DESTROY: NZCIDV * * ^^^ ^ * * * * CYCLES: 5231+ * * SIZE: 2707 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ]FNSTR EQU WPAR1 ]LDADDR EQU WPAR2 ]FLEN EQU WPAR3 ]SLOT EQU BPAR1 ]DRIVE EQU BPAR2 ]VOL EQU BPAR3 * FBSAVE * ** FIRST, OPEN THE FILE FOR BINARY WRITING * FOPEN ]FNSTR;]SLOT;]DRIVE;]VOL;#0;#]TYP_BIN ; {828C433B} * ** NEXT, STORE THE STARTING ADDRESS OF THE ** MEMORY RANGE AT THE FIRST TWO BYTES OF THE FILE. * FWRTB ]SLOT;]DRIVE;]VOL;#0;#0;]LDADDR ; {665C337B} FWRTB ]SLOT;]DRIVE;]VOL;#0;#1;]LDADDR+1 ; {665C337B} * ** NOW STORE THE LENGTH IN THE THIRD AND FOURTH ** BYTES OF THE FILE. * FWRTB ]SLOT;]DRIVE;]VOL;#0;#2;]FLEN ; {665C337B} FWRTB ]SLOT;]DRIVE;]VOL;#0;#3;]FLEN+1 ; {665C337B} * ** THEN STORE THE MEMORY RANGE IN THE FILE, OFFSETTING ** BY FOUR TO ACCOUNT FOR THE PRECEDING ADDRESS AND ** LENGTH BYTES. * FWRTR ]SLOT;]DRIVE;]VOL;#0;#4;]LDADDR;]FLEN ; {940C509B} * ** CLOSE FILE, RETURN TO CALLER * FCLOS ]FNSTR;]SLOT;]DRIVE {797C416B} RTS ; {6C1B} ``` --- ## Miscellaneous DOS Macros The MAC.DOSMORE.ASM file contains macros that are primarily concerned with DOS functions but are not required and do not fit neatly in with file management. This includes macros for checking the DOS version, verifying if DOS or Applesoft is loaded, and macros for telling if an Applesoft or Integer BASIC program is running. `LISTING 6.60: MAC.DOSMORE.ASM Heading` ```assembly * *``````````````````````````````* * MAC.DOSMORE.ASM * * * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * DATE: 20-APR-2021 * * ASSEMBLER: MERLIN 8 PRO * * OS: DOS 3.3 * * * * SUBROUTINE FILES USED * * * * NONE * * * * LIST OF MACROS * * * * DVER : CHECK DOS VERSION * * DOSIN : CHECK IF DOS LOADED * * ABAS : IS APPLESOFT LOADED * * IBEX : IS INTEGER BASIC * * PROGRAM RUNNING * * ABEX : IS APPLESOFT BASIC * * PROGRAM RUNNING * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ``` --- ### THE DVER MACRO _SUMMARY_ | Condition | Value | | --------------- | --------------------- | | Name | `DVER` | | Type | Macro | | File | `MAC.DOSMORE.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Check the DOS version | | Input | none | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 28+ | | Bytes | 18 | | Notes | none | | See Also | none | --- *DETAILS* The `DVER` macro checks the current version of DOS in memory and returns the version number in the **.A** register. `LISTING 6.61: MAC.DOSMORE.ASM DVER Macro Source` ```assembly * *``````````````````````````````* * DVER (NATHAN RIGGS) * * * * RETURN THE DOS VERSION. THIS * * IS ADAPTED FROM DON WORTH'S * * AND PIETER LECHNER'S * * /BENEATH APPLE DOS/. THE * * LICENSE MAY ACCORDINGLY * * VARY. * * * * PARAMETERS * * * * NONE * * * * CYCLES: 28 * * SIZE: 18 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * DVER MAC CLC ; {2C1B} CLEAR CARRY FLAG LDA #0 ; {3C2B} CLEAR ACCUMULATOR ADC #$BE ; {2C2B} ADD #$16BE TO DOS LOAD POINT STA ADDR1 ; {3C2B} STORE LOW BYTE LDA $3D2 ; {4C3B} LOAD DOS LOADING POINT ADC #$16 ; {2C2B} ADD OFFSET STA ADDR1+1 ; {3C2B} STORE HIGH BYTE LDY #0 ; {3C2B} SET INDEX TO 0 LDA (ADDR1),Y ; {6C2B} RETURNS #2 OR #3 FOR ; THE DOS VERSION IN .A <<< * ``` --- ### THE DOSIN MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------- | | Name | `DOSIN` | | Type | Macro | | File | `MAC.DOSMORE.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Check if DOS is loaded | | Input | none | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 17+ | | Bytes | 12 | | Notes | none | | See Also | none | --- *DETAILS* The `DOSIN` macro checks if DOS is currently loaded into memory. The **CARRY** flag is set if DOS is loaded, and it is cleared if DOS is not loaded. `LISTING 6.62: MAC.DOSMORE.ASM DOSIN Macro Source` ```assembly * *``````````````````````````````* * DOSIN * * * * CHECKS IF DOS IS LOADED. * * THIS SHOULD BE CALLED BEFORE * * RUNNING RWTS OR THE FILE * * MANAGER. * * * * THIS IS ADAPTED FROM DON * * WORTH'S AND PIETER LECHNER'S * * /BENEATH APPLE DOS/, SO THE * * LICENSE MAY VARY ACCORDINGLY * * * * PARAMETERS * * * * NONE * * * * CYCLES: 17 * * SIZE: 12 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * DOSIN MAC LDA $3D0 ; {4C3B} GET VECTOR JUMP CMP #$4C ; {3C2B} IS IT A JUMP? BNE ]NODOS ; {3C2B} NOPE, JUMP TO NONE SEC ; {2C1B} CARRY SET, MEANING DOS LOADED JMP ]EXIT ; {3C3B} ]NODOS CLC ; {2C1B} CARRY CLEAR, MEANING NO DOS ]EXIT <<< * ``` --- ### THE ABAS MACRO _SUMMARY_ | Condition | Value | | --------------- | ------------------------------------- | | Name | `ABAS` | | Type | Macro | | File | `MAC.DOSMORE.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Find out which BASIC system is loaded | | Input | none | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 40+ | | Bytes | 29 | | Notes | none | | See Also | none | --- *DETAILS* The `ABAS` macro determines whether it is Applesoft BASIC or Integer BASIC that is currently loaded. If Applesoft BASIC is loaded, then the **CARRY** is set; if it is Integer BASIC loaded, then the **CARRY** is cleared. `LISTING 6.63: MAC.DOSMORE.ASM ABAS Macro Source` ```assembly * *``````````````````````````````* * ABAS * * * * DETERMINE WHICH BASIC IS * * LOADED. IF CARRY IS CLEAR, * * THEN INTEGER BASIC IS * * LOADED--ELSE, APPLESOFT IS. * * * * THIS IS ADAPTED FROM DON * * WORTH'S AND PIETER LECHNER'S * * /BENEATH APPLE DOS/, SO THE * * LICENSE MAY VARY ACCORDINGLY * * * * PARAMETERS * * * * NONE * * * * CYCLES: 40 * * SIZE: 29 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ABAS MAC LDA #$4C ; {4C3B} CODE FOR APPLESOFT ; #$20 IS FOR INTEGER BASIC CMP $E000 ; {4C3B} CORRECT BASIC ALREADY THERE? BEQ ]APPLES ; {3C2B} YES, GOTO RETURN CARRY STA $C080 ; {4C3B} NOW IS IT THERE? CMP $E000 ; {4C3B} NOW IS IT THERE? BEQ ]APPLES ; {3C2B} YEP, GOTO RETURN CARRY STA $C081 ; {4C3B} STILL NO, TRY ROM CARD CMP $E000 ; {4C3B} THERE NOW? BEQ ]APPLES ; {3C2B} YEP, GOTO RETURN CARRY ; NOPE, DON'T RETURN CARRY CLC ; {2C1B} JMP ]EXIT ; {3C3B} ]APPLES SEC ; {2C1B} ]EXIT <<< * ``` --- ### THE IBEX MACRO _SUMMARY_ | Condition | Value | | --------------- | -------------------------------------------- | | Name | `IBEX` | | Type | Macro | | File | `MAC.DOSMORE.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Check if an Integer BASIC program is running | | Input | none | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 17+ | | Bytes | 12 | | Notes | none | | See Also | none | --- *DETAILS* The `IBEX` macro sets the **CARRY** flag if an Integer BASIC program is currently running; otherwise, the **CARRY** is cleared. `LISTING 6.64: MAC.DOSMORE.ASM IBEX Macro Source` ```assembly * *``````````````````````````````* * IBEX * * * * CHECK IF AN INTEGER BASIC * * PROGRAM IS RUNNING. * * * * THIS IS ADAPTED FROM DON * * WORTH'S AND PIETER LECHNER'S * * /BENEATH APPLE DOS/, SO THE * * LICENSE MAY VARY ACCORDINGLY * * * * PARAMETERS * * * * NONE * * * * CYCLES: 17 * * SIZE: 12 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * IBEX MAC LDA $D9 ; {4C3B} CHECK BASIC BMI ]YES ; {3C2B} IF NEG, THEN INT BASIC RUNNING BPL ]NO ; {3C2B} IF POSITIVE, THEN NOT ]YES SEC ; {2C1B} INT BASIC RUNNING, SET CARRY JMP ]EXIT ; {3C3B} AND EXIT ]NO CLC ; {2C1B} NOT RUNNING, SO CLEAR CARRY ]EXIT ; AND EXIT <<< * ``` --- ### THE ABEX MACRO _SUMMARY_ | Condition | Value | | --------------- | ---------------------------------------------- | | Name | `ABEX` | | Type | Macro | | File | `MAC.DOSMORE.ASM` | | Author | Nathan Riggs | | Last Revision | 07-MAY-2021 | | Assembler | Merlin Pro 8 | | OS | Apple DOS 3.3 | | Purpose | Check if an Applesoft BASIC program is running | | Input | none | | Output | none. | | Dependencies | none | | Flags Destroyed | NZCV | | Cycles | 26+ | | Bytes | 18 | | Notes | none | | See Also | none | --- *DETAILS* The `ABEX` macro sets the **CARRY** flag if an Applesoft BASIC program is currently running; otherwise, the **CARRY** is cleared. `LISTING 6.65: MAC.DOSMORE.ASM ABEX Macro Source` ```assembly * *``````````````````````````````* * ABEX * * * * CHECK IF AN APPLESOFT BASIC * * PROGRAM IS RUNNING. * * * * THIS IS ADAPTED FROM DON * * WORTH'S AND PIETER LECHNER'S * * /BENEATH APPLE DOS/, SO THE * * LICENSE MAY VARY ACCORDINGLY * * * * PARAMETERS * * * * NONE * * * * CYCLES: 26 * * SIZE: 18 BYTES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ABEX MAC LDX $76 ; {4C3B} GET LINE NUMBER INX ; {2C1B} BEQ ]NO ; {3C2B} LDX $33 ; {4C3B} GET PROMPT CHARACTER CPX #$DD ; {3C2B} IS PROMPT A "]" ? BEQ ]NO ; {3C2B} YES, SO NOT EXECUTING SEC ; {2C1B} ELSE, IS EXECUTING--SET CARRY JMP ]EXIT ; {3C3B} ]NO CLC ; {2C1B} ]EXIT <<< * ``` --- ## Part II: DOS Collection Demos This section lists two demo files, DEMO.DOSFM.ASM and DEMO.DOSMORE.ASM, that illustrate how to use the various macros in the DOS collection. This only concerns the macros found in the MAC.DOSFM.ASM file and the MAC.DOSMORE.ASM file, as the macros in DOS.DOSREQ.ASM are meant for internal use only. `Listing 6.70: DEMO.DOSFM.ASM Source` ```assembly * *``````````````````````````````* * DEMO.DOSFM.ASM * * * * A DEMO FILE FOR THE DOS * * FILE MANAGER MACROS. * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * DATE: 21-APR-2021 * * ASSEMBLER: MERLIN 8 PRO * * OS: DOS 3.3 * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** ASSEMBLER DIRECTIVES * CYC AVE EXP OFF TR ON DSK DEMO.DOSFM OBJ $BFE0 ORG $6000 * *``````````````````````````````* * TOP INCLUDES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * PUT MIN.HEAD.REQUIRED.ASM USE MIN.MAC.REQUIRED.ASM USE MIN.MAC.DOSREQ.ASM USE MIN.MAC.DOSFM.ASM PUT MIN.HEAD.DOS.ASM * ]HOME EQU $FC58 ]ZSLOT EQU $6 ]ZDRIVE EQU $2 * *``````````````````````````````* * PROGRAM MAIN BODY * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * *``````````````````````````````* * DOS FILE MANAGER MACROS * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FOLLOWING MACROS BEING USED ARE EXAMPLES ** OF HOW TO USE EACH MACRO IN THE FILE MANAGER ** MACRO SELECTION OF THE DOS COLLECTION OF THE ** APPLEIIASM LIBRARY. NOTE THAT OTHER DEMO FILES ** EXIST FOR OTHER DOS FUNCTIONS, SUCH AS THE ** DEMO.DOSRWTS.ASM FILE FOR RWTS USAGE AND THE ** DEMO.DOSMORE.ASM FILE FOR MISCELLANEOUS MACROS ** THAT CAN BE OF USE WHILE USING APPLE DOS. * *``````````````````````````````* * THE FCAT MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FCAT MACRO SIMPLY RUNS THE CATALOG ** DOS COMMAND, WHICH LISTS THE FILES IN A ** DISK IN THE GIVEN SLOT AND DRIVE. A MORE ** ROBUST CATALOGING MACRO IS PLANNED AS PART ** OF THE DEMO.DOSMORE.ASM SELECTION. * JSR ]HOME _PRN "THE FCAT MACRO",8D _PRN "==============",8D8D _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * THE FLOCK MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FLOCK MACRO LOCKS A GIVEN FILE AT THE ** PROVIDED SLOT AND DRIVE NUMBERS. * JSR ]HOME _PRN "THE FLOCK MACRO",8D _PRN "===============",8D8D _PRN "FIRST, CATALOG BEFORE LOCKING:",8D8D _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT _PRN " ",8D _PRN "NOW LOCK A FILE AND DO ANOTHER CAT:",8D8D FLOCK #FN5;#]ZSLOT;#]ZDRIVE _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * THE FULCK MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FULCK MACRO SIMPLY UNLOCKS A FILE IN ** THE GIVEN SLOT AND DRIVE. * JSR ]HOME _PRN "THE FULCK MACRO",8D _PRN "===============",8D8D _PRN "FIRST, SHOW CATALOG WITH LOCKED FILE:",8D8D _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT _PRN " ",8D _PRN "NOW SHOW CATALOG WITH UNLOCKED FILE:",8D8D FULCK #FN5;#]ZSLOT;#]ZDRIVE _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * THE FRENM MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FRENM MACRO RENAMES A FILE FROM A SOURCE ** FILENAME TO A DESTINATION FILENAME, BOTH IN ** THE SAME SLOT AND DRIVE. * JSR ]HOME _PRN "THE FRENM MACRO",8D _PRN "===============",8D8D _PRN "CATALOG WITH RENAMED FILE:",8D8D FRENM #FN5;#FN3;#]ZSLOT;#]ZDRIVE _WAIT FCAT #]ZSLOT;#]ZDRIVE _PRN " ",8D _WAIT _PRN "CATALOG WITH FILE RENAMED BACK:",8D8D _WAIT FRENM #FN3;#FN5;#]ZSLOT;]ZDRIVE FCAT #]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * THE FWRTB MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FWRTB MACRO, WHICH STANDS FOR ** (F)ILE (WR)I(T)E (B)YTE, WRITES A SINGLE BYTE ** TO A FILE ON A DISK AT A GIVEN SLOT, DRIVE AND ** VOLUME. NOTE THAT THIS CAN BE ANY FILE TYPE. * ** OTHER THAN THE RETURN CODE, THERE IS NO OUTPUT ** BEYOND THE "A" BEING PUT INTO THE FILE. WE CANNOT ** TEST THIS UNTIL WE ALSO USE A BYTE READING FUNCTION, ** WHICH WE WILL COVER NEXT. * ** ALSO NOTE THAT THIS MAKES USE OF THE FOPEN AND FCLOS ** MACROS. THESE WILL BE EXHIBITED AGAIN TOWARD THE END ** OF THE DEMO. * FOPEN #FN5;#]ZSLOT;#]ZDRIVE;#0;#0;#]TYP_TXT FWRTB #]ZSLOT;#]ZDRIVE;#0;#0;#0;#"A" FCLOS #FN5;#]ZSLOT;#]ZDRIVE * *``````````````````````````````* * THE FRDB MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FRDB MACRO, WHICH STANDS FOR ** (F)ILE (R)EA(D) (B)YTE, READS A BYTE FROM ** A FILE ON A DISK IN THE GIVEN SLOT, DRIVE AND ** VOLUME. * JSR ]HOME _PRN "THE FRDB AND FWRTB MACROS",8D _PRN "=========================",8D8D _PRN "THE FIRST BYTE OF THE FILE IS: " FOPEN #FN5;#]ZSLOT;#]ZDRIVE;#0;#0;#]TYP_TXT FRDB #]ZSLOT;#]ZDRIVE;#0;#0;#0;#0 JSR $FDF0 FCLOS #FN5;#]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * THE FWRTR MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FWRTR MACRO, WHICH STANDS FOR (F)ILE ** (WR)I(T)E RANGE, WRITES A RANGE OF BYTES IN ** MEMORY TO A FILE (THE TYPE IS UP TO THE USER). ** THIS IS USED IN CONJUNCTION WITH THE FRDR MACRO ** TO READ AND WRITE MULTIPLE BYTES FROM AND TO FILES. * ** THIS MACRO ONLY OUTPUTS TO A FILE, SAVE FOR THE ** RETURN CODE STORED IN THE .X REGISTER. THE NEXT ** MACRO'S EXPLANATION WILL INCLUDE PRINTING THE TEXT ** SAVED TO A FILE HERE. * ** NOTE THAT WHEN WRITING A RANGE OF BYTES, THE LENGTH ** OF THE BYTES TO BE WRITTEN SHOULD BE REDUCED BY ONE. ** THIS IS DUE TO AN INCONSISTENCY IN DOS. * FOPEN #FN5;#]ZSLOT;#]ZDRIVE;#0;#0;#]TYP_TXT FWRTR #]ZSLOT;#]ZDRIVE;#0;#0;#0;#RANGE+1;#24 FCLOS #FN5;#]ZSLOT;#]ZDRIVE * *``````````````````````````````* * THE FRDR MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FRDR MACRO, WHICH STANDS FOR (F)ILE ** (R)EA(D) (R)ANGE, READS A RANGE OF BYTES ** FROM A FILE ON A DISK AT A GIVEN SLOT AND DISK, ** STORING THE DATA AT A PROVIDED ADDRESS. IT ** IS IMPORTANT TO KNOW THE SIZE OF THE FILE ** PRIOR TO READING IT, SINCE READING PAST THE ** END OF THE FILE CAN HAVE UNPREDICTABLE ** CONSEQUENCES. * JSR ]HOME _PRN "THE FRDR AND FWRTR MACROS",8D _PRN "=========================",8D8D _PRN "THE FILE CONTAINS:",8D8D FOPEN #FN5;#]ZSLOT;#]ZDRIVE;#0;#0;#0 FRDR #]ZSLOT;#]ZDRIVE;#0;#0;#0;#RDRANGE;#25 FCLOS #FN5;#]ZSLOT;#]ZDRIVE LDY #255 LOOP1 INY LDA RDRANGE,Y JSR $FDF0 CPY #24 BNE LOOP1 _WAIT * *``````````````````````````````* * THE BLOAD MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE BLOAD MACRO WORKS MUCH LIKE THE BLOAD ** COMMAND IN DOS, BUT THERE IS NO BLOAD COMMAND ** FOR THE FILE MANAGER; IT HAS TO BE BUILT FROM ** THE ALREADY AVAILABLE COMMANDS. * ** WHEN USED, THE BLOAD MACRO LOADS A BINARY FILE'S ** CONTENTS AND STORES THEM IN THE PROVIDED ADDRESS ON ** THE DISK IN THE GIVEN SLOT AND DRIVE. IF THE ADDRESS ** PASSED IS #0000, THEN THE MACRO/SUBROUTINE ASSUMES ** THAT THE DEFAULT ADDRESS WILL BE USED, WHICH IS ** STORED IN THE FIRST TWO BYTES OF THE FILE. THE LENGTH ** IS ALSO STORED AT THE BEGINNING OF THE FILE IN BYTES ** THREE AND FOUR, FOLLOWED BY THE ACTUAL DATA REQUESTED. * ** IT SHOULD BE NOTED THAT THERE IS NO TEXT FILE ** EQUIVALENT TO BLOAD BECAUSE ANYONE WITH ANY SENSE ** WILL USE BINARY FILES TO STORE AND RETRIEVE DATA ON ** THE DISK, AS IT IS BOTH FASTER AND EASIER--TEXT ** FILES, FOR INSTANCE, DO NOT EASILY PROVIDE THE ** LENGTH OF THE FILE. IF A TEXT ROUTINE AS SUCH IS ** NEEDED, IT IS BEST TO BUILD YOUR OWN USING FWRTR, ** FRDR, FWRTB AND FRDB, AS YOU WILL LIKELY CREATE YOUR ** OWN STRUCTURE TO THE FILE. * JSR ]HOME _PRN "THE BLOAD MACRO",8D _PRN "===============",8D8D _PRN "$300 NOW HOLDS:",8D8D BLOAD #FN6;#$0000;#]ZSLOT;#]ZDRIVE;#0 DUMP #$300;#$40 _WAIT * *``````````````````````````````* * THE BSAVE MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE BSAVE MACRO IS FUNCTIONALLY EQUIVALENT TO ** THE BSAVE COMMAND FROM THE DOS PROMPT. FIRST, ** THE PROVIDED ADDRESS IS STORED IN THE FIRST TWO ** BYTES OF THE FILE TO SUPPLY THE DEAULT LOADING ** ADDRESS. FOLLOWING THAT, THE LENGTH OF THE DATA ** IS STORED IN THE THIRD AND FOURTH BYTES. THE ** DATA IS THEN STORED FOLLOWING THESE BYTES. THIS ** IS HOW DOS ITSELF HANDLES BINARY FILES, AND ** YOUR BINARY FILES SHOULD ALSO FOLLOW THIS SCHEME ** TO AVOID ANGERING THE GODS. * ** WE WON'T BE GOING THROUGH THE OUTPUT HERE, BUT IF ** YOU EXAMINE THE FILE WITH A TOOL LIKE CIDERPRESS, ** YOU WILL SEE THAT THE FILE SIMPLY CONTAINS THE ** VALUES #$01 TO #$40. BE FOREWARNED THAT YOU WILL ** NOT SEE THE FIRST FOUR BYTES, AS CIDERPRESS HIDES ** THESE TO PREVENT CONFUSION. YOU CAN VIEW THE FIRST ** FOUR BYTES BY LOOKING AT THE SECTOR THE FILE STARTS ** AT. * ** NOTE AGAIN THAT AN EQUIVALENT MACRO OR SUBROUTINE ** IS NOT PROVIDED IN THIS COLLECTION. * JSR ]HOME _PRN "THE BSAVE MACRO",8D _PRN "===============",8D8D _PRN "SAVING BINARY DATA..." BSAVE #FN7;#MEM40;#$39;#6;#2;#0 _PRN "DONE!!!",8D8D _WAIT * *``````````````````````````````* * THE FOPEN AND FCLOS MACROS * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE FOPEN MACRO MUST BE RUN BEFORE READING ** OR WRITING A FILE, AND THE FCLOS MACRO MUST ** BE USED AFTERWARDS. IF FOPEN IS NEGLECTED, THE ** FILE WILL NOT BE CREATED; IF FCLOS IS NEGLECTED, ** THEN THAT FILE BUFFER WILL REMAIN IN USE. SINCE ** WE GENERALLY LIKE TO ACTUALLY USE OUR FILES, IT'S ** GOOD PRACTICE TO USE FOPEN AND FCLOS BECAUSE ** UM.. FILE INPUT AND OUTPUT WOULD NOT HAPPEN OTHERWISE. * ** IF A FILE DOES NOT ALREADY EXIST, FOPEN AUTOMATICALLY ** CREATES A NEW ONE WITH THE PROVIDED FILENAME. HERE, ** WE WILL CREATE A FILE CALLED "TODELETE" THAT WILL BE ** DELETED IN THE NEXT MACRO'S EXPLANATION. * JSR ]HOME _PRN "FOPEN AND FCLOS",8D _PRN "===============",8D8D _PRN "CATALOG BEFORE FILE CREATION:",8D8D _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT _PRN " ",8D _PRN "CATALOG AFTER FILE CREATION:",8D8D FOPEN #FN8;#]ZSLOT;#]ZDRIVE;#0;#0;#]TYP_TXT FCLOS #FN8;#]ZSLOT;#]ZDRIVE _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * THE FDEL MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** LASTLY (FOR GOOD REASON), THE FDEL MACRO ** DELETES A FILE WITH THE GIVEN NAME IN THE ** NOTED SLOT AND DISK DRIVE. HERE, LET US ** DELETE THE LAST FILE WE CREATED, "TODELETE". * JSR ]HOME _PRN "THE FDEL MACRO",8D _PRN "==============",8D8D _PRN "LOOK MA, NO TODELETE FILE!",8D8D FDEL #FN8;#]ZSLOT;#]ZDRIVE _WAIT FCAT #]ZSLOT;#]ZDRIVE _WAIT * *``````````````````````````````* * RWTS MACROS * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** WHILE THE RWTS ROUTINE HAS NOT BEEN ABSTRACTED ** TOO MUCH, THIS IS FOR GOOD REASON: OUR HEADER ** FILE IS GETTING TOO BIG FOR ITS BRITCHES! * ** THE RWTS ROUTINE LETS YOU READ AND WRITE DIRECTLY ** TO A DISK, BYPASSING CONVENTIONS USED BY DOS. ** IT GOES WITHOUT SAYING THAT THIS IS DANGEROUS: THE ** SMALLEST ACCIDENT CAN DESTROY A DISK FOR GOOD, SO ** USE THIS AT YOUR OWN DISCRETION. * ** THERE ARE TWO MAIN MACROS FOR USING RWTS: THE SRWTS ** MACRO ( (S)ET RWTS ) AND THE GRWTS MACRO. THE SRWTS ** MACRO MUST ALWAYS BE RUN BEFORE GRWTS, AS IT SETS ** THE VARIABLES NEEDED FOR RWTS TO WORK. SINCE THERE ** IS SUCH A THREAT OF DISK CORRUPTION, WE ARE ONLY ** SHOWING HOW TO USE RWTS TO READ THE DISK, NOT WRITE ** IT; HOWEVER, THE PROCESS IS THE SAME FOR BOTH. * JSR ]HOME _PRN "THE RWTS MACROS",8D _PRN "===============",8D8D JSR ]LOCRPL STY ]RWTSPTR STA ]RWTSPTR+1 * SRWTS #]ZSLOT;#]ZDRIVE;#0;#$11;#0;#$9000;#1 GRWTS _PRN "HERE'S THE DISK VTOC:",8D8D DUMP #$9000;#$F DUMP #$9010;#$F DUMP #$9020;#$F DUMP #$9030;#$F DUMP #$9040;#$F DUMP #$9050;#$F DUMP #$9060;#$F DUMP #$9070;#$F _PRN " ",8D _PRN ".....",8D _WAIT * JSR ]HOME _PRN "FIN!",8D8D * EXIT JMP $3D0 * PUT MIN.SUB.FBLOAD.ASM PUT SUB.FBSAVE.ASM PUT MIN.LIB.REQUIRED.ASM * FN3 STR "RENAMED" FN5 STR "WRITERANGE" FN6 STR "BINLOAD" FN7 STR "BINSAVE" FN8 STR "TODELETE" MEM40 HEX 000102030405060708091A1B1C1D1E1F HEX 101112131415161718191A1B1C1D1E1F HEX 202122232425262728292A2B2C2D2E2F HEX 303132333435363738393A3B3C3D3E3F RANGE STR "ONE RING TO RULE THEM ALL" RDRANGE DS 25 * ``` `Listing 6.71: DEMO.DOSMORE.ASM Source` ```assembly * *``````````````````````````````* * DEMO.DOSMORE.ASM * * * * A DEMO FILE FOR VARIOUS DOS * * MACROS AND SUBROUTINES. * * * * AUTHOR: NATHAN RIGGS * * CONTACT: NATHAN.RIGGS@ * * OUTLOOK.COM * * * * DATE: 07-MAY-2021 * * ASSEMBLER: MERLIN 8 PRO * * OS: DOS 3.3 * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** ASSEMBLER DIRECTIVES * CYC AVE EXP OFF TR ON DSK DEMO.DOSMORE OBJ $BFE0 ORG $6000 * *``````````````````````````````* * TOP INCLUDES * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * PUT MIN.HEAD.REQUIRED.ASM USE MIN.MAC.REQUIRED.ASM USE MIN.MAC.DOSREQ.ASM USE MIN.MAC.DOSMORE.ASM PUT MIN.HEAD.DOS.ASM ]HOME EQU $FC58 * *``````````````````````````````* * PROGRAM MAIN BODY * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * *``````````````````````````````* * MISC. DOS MACROS * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * *``````````````````````````````* * DVER * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE DVER MACRO TESTS WHICH DOS VERSION IS ** BEING USED. IT RETURNS #2 FOR DOS 3.2 AND #3 ** FOR DOS 3.X. * JSR ]HOME _PRN "DOS VERSION MACRO (DVER)",8D _PRN "========================",8D8D DVER CMP #3 BEQ THREE _PRN "USING DOS 2.X",8D JMP NEXT1 THREE _PRN "USING DOS 3.X",8D NEXT1 _WAIT * *``````````````````````````````* * THE DOSIN MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE DOSIN MACRO CHECK WHETHER DOS IS LOADED. ** THIS IS NECESSARY TO CHECK BEFORE TRYING TO ** USE THE DOS FILE MANAGER OR THE RWTS ROUTINES. * JSR ]HOME _PRN "THE DOSIN MACRO",8D _PRN "===============",8D8D DOSIN BCC NODOS _PRN "DOS IS CURRENTLY LOADED." JMP NEXT2 NODOS _PRN "DOS IS NOT LOADED." NEXT2 _WAIT * *``````````````````````````````* * THE ABAS MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE ABAS MACRO TESTS WHICH VERSION OF ** BASIC IS LOADED: INTEGER OR APPLESOFT. ** IF APPLESOFT IS LOADED, THEN THE CARRY IS ** RETURNED AS TRUE; IF INTEGER BASIC IS LOADED, ** THEN THE CARRY IS RETURNED CLEAR. * JSR ]HOME _PRN "THE ABAS MACRO",8D _PRN "==============",8D8D ABAS BCC INTBAS _PRN "APPLESOFT IS LOADED." JMP NEXT3 INTBAS _PRN "INTEGER BASIC IS LOADED." NEXT3 _WAIT * *``````````````````````````````* * THE IBEX MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE IBEX MACRO TESTS WHETHER INTEGER BASIC ** IS RUNNING. THE CARRY IS RETURNED AS TRUE IF SO, ** AND CLEAR IF NOT. NOTE THAT YOU SHOULD TEST IF ** INTEGER BASIC IS LOADED BEFOREHAND; OTHERWISE, ** A FALSE POSITIVE MAY RESULT. * JSR ]HOME _PRN "THE IBEX MACRO",8D _PRN "==============",8D8D IBEX BCC INTNORUN _PRN "INTEGER BASIC IS RUNNING." JMP NEXT4 INTNORUN _PRN "INTEGER BASIC IS NOT RUNNING." NEXT4 _WAIT * *``````````````````````````````* * THE ABEX MACRO * *,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,* * ** THE ABEX MACRO TESTS WHETHER AN APPLESOFT ** PROGRAM IS CURRENTLY RUNNING. * JSR ]HOME _PRN "THE ABEX MACRO",8D _PRN "==============",8D8D ABEX BCC NOAPP _PRN "APPLESOFT PROGRAM IS RUNNING." JMP NEXT5 NOAPP _PRN "APPLESOFT PROGRAM IS NOT RUNNING." NEXT5 _WAIT * JSR ]HOME _PRN "FIN!",8D8D * EXIT JMP $3D0 * PUT MIN.LIB.REQUIRED.ASM * ```