mirror of
https://github.com/opsxcq/mirror-textfiles.com.git
synced 2025-08-08 13:16:27 +02:00
update
This commit is contained in:
1109
textfiles.com/apple/ANATOMY/cmdwrite.txt
Normal file
1109
textfiles.com/apple/ANATOMY/cmdwrite.txt
Normal file
File diff suppressed because it is too large
Load Diff
798
textfiles.com/apple/ANATOMY/dissassembly.er.txt
Normal file
798
textfiles.com/apple/ANATOMY/dissassembly.er.txt
Normal file
@@ -0,0 +1,798 @@
|
||||
******************************************************************
|
||||
* *
|
||||
* DISASSEMBLY OF ERRORS *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* Assembly language programmers should appreciate the fact *
|
||||
* that debugging and error trapping a program often requires *
|
||||
* considerable more time than simply coding the routines needed *
|
||||
* to perform the tasks originally intended. Anyone who plans to *
|
||||
* modify DOS or access DOS from an assembly language program *
|
||||
* should therefore be thoroughly familiar with DOS's error- *
|
||||
* handling routines. Unfortunately, this is not an easy task *
|
||||
* because: *
|
||||
* 1) Hundreds of lines of code and dozens of decisions and *
|
||||
* flags may be required to process a simple error from *
|
||||
* the point of detection to the actual printing of the *
|
||||
* error message. *
|
||||
* 2) The evolution of DOS has not always been a smooth *
|
||||
* process. Some error-handling routines have been *
|
||||
* patched more times than a miser's favorite pair of *
|
||||
* socks. *
|
||||
* 3) Some error-handling routines reset the stack pointer *
|
||||
* to govern the execution pattern. The values used to *
|
||||
* adjust the stack pointer are not always readily *
|
||||
* apparent. *
|
||||
* 4) Some command handlers call other command handlers. *
|
||||
* 5) Some command handlers use both function and subfunction*
|
||||
* handlers whereas other commands use neither. *
|
||||
* 6) DOS employs approximately 14 different levels of sub- *
|
||||
* routines. It is therefore often very difficult simply *
|
||||
* to keep the implications of a given command in *
|
||||
* perspective. *
|
||||
* Considering these difficulties, it doesn't seem feasible *
|
||||
* to describe all the different potential execution patterns *
|
||||
* associated with DOS's error-handling routines in a single *
|
||||
* formatted disassembly. However, the following listing should, *
|
||||
* WHEN USED WITH THE OTHER FORMATTED DISASSEMBLIES, help you *
|
||||
* trace any DOS error to its bitter end. In order to help you *
|
||||
* keep things in perspective, note that this listing uses PHONY *
|
||||
* command, function and subfunction handlers to depict a *
|
||||
* MYTHICAL command that is vulnerable to every type of error in *
|
||||
* DOS. Also note that a given subroutine may be accessed at *
|
||||
* different depths of execution by different commands. (For *
|
||||
* instance, PhonycommandhandlerA may access the BADFMXIT routine *
|
||||
* ($B385) at a level five subroutines deeper than the command *
|
||||
* handler's entry point. On the other hand, PhonycommandhandlerB *
|
||||
* may enter BADFMXIT at a level seven subroutines deeper than *
|
||||
* the command handler's entry point.) *
|
||||
* *
|
||||
*================================================================*
|
||||
* *
|
||||
* DOS ACCESS VS ERROR HANDLING *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* Assembly language programmers who access DOS via the *
|
||||
* file manager should note that they must write their own error- *
|
||||
* handling routines. Where necessary, these routines should *
|
||||
* close files, release DOS buffers and print the appropriate *
|
||||
* error messages. *
|
||||
* Whenever possible, (nonturnkey) assembly language *
|
||||
* programs intended for commerical distribution should be *
|
||||
* designed to run on different-sized machines or accommodate *
|
||||
* moved versions of DOS. Under these conditions, DOS must be *
|
||||
* accessed via indirect addressing. Only the filemanager *
|
||||
* (ie. DOS's function and subfunction handlers) and RWTS are *
|
||||
* readily accessible through indirect addressing. All other *
|
||||
* sections of DOS (including the command handlers, the error- *
|
||||
* handling routines and DOS's command parsing and processing *
|
||||
* routines) are off limits. It is therefore the programmer's *
|
||||
* responsibility, to write his own supporting routines. These *
|
||||
* routines must not only handle errors, but they must also *
|
||||
* detect certain errors. (For example, none of the indirectly *
|
||||
* accessible portions of DOS check a file description entry to *
|
||||
* determine if the file found is of the correct type or not. *
|
||||
* This is just another one of the duties of the program author.) *
|
||||
* Some programmers implement DOS commands by direct calls *
|
||||
* or by printing a string containing a return, control-D and the *
|
||||
* characters of a DOS command. If you employ either of these *
|
||||
* techniques, you should take special note of the ERRHNDLR *
|
||||
* ($A6D2) and CKBSCRUN ($A65E) routines. Several flags in these *
|
||||
* routines are responsible for determining the route taken to *
|
||||
* exit DOS and whether or not an error message should be printed.*
|
||||
* If you want DOS to exit to your own custom error-handling *
|
||||
* routine, be sure to place the address of your error handler in *
|
||||
* ADBSCERR ($9D5A, $9D5B) and condition the following flags as *
|
||||
* indicated: *
|
||||
* ACTBSFLG ($AAB6): $40 ;Denotes Applesoft. *
|
||||
* CURLIN+1 ($76): not $FF ;$FF denotes immediate mode. *
|
||||
* PROMPT ($33): not $DD ;$DD = RH bracket = Applesoft *
|
||||
* ;prompt. *
|
||||
* If you want DOS to print an error message before entering your *
|
||||
* error handler, you must also insure that the on-err flag *
|
||||
* (ERRFLG, $D8) contains a positive value. *
|
||||
* *
|
||||
******************************************************************
|
||||
|
||||
|
||||
|
||||
***********************
|
||||
* *
|
||||
* Line parsing and *
|
||||
* command recognition *
|
||||
* routine. *
|
||||
* *
|
||||
*---------------------*
|
||||
(9FCD)
|
||||
PARSECMD .
|
||||
.
|
||||
.
|
||||
.
|
||||
(A018) .
|
||||
PRSYNERR JMP SYNTXERR ;A DOS command was expected but not found.
|
||||
. ;- OR a filename was required but not issued.
|
||||
. ;- OR an illegal filename character was used.
|
||||
. ;- OR an option not applicable to the
|
||||
. ; command was used.
|
||||
. ;- OR IN#, PR# or MAXFILES arguments were
|
||||
. ; not in the correct range.
|
||||
.
|
||||
(A02D) .
|
||||
NODIRCMD LDA #15 ;An attempt was made to issue a READ, WRITE,
|
||||
(A02F) JMP ERRHNDLR ;POSITION, OPEN or APPEND command in the
|
||||
. ;immediate mode.
|
||||
.
|
||||
(A0C9) .
|
||||
ARGRNGER LDA #2 ;Argument issued with the IN#, PR#
|
||||
(A0CB) JMP ERRHNDLR ;or MAXFILES commands or A, B, R, L, S, D
|
||||
. ;or V options was too large or too small.
|
||||
.
|
||||
(A0CE) .
|
||||
TOSYNTX JMP SYNTXERR ;An option character was expected but not
|
||||
. ;issued with the command.
|
||||
. ;A non-numeric char was issued as an
|
||||
. ;arugment for the IN#, PR#, or MAXFILES
|
||||
. ;commands or for the A, B, R, L, S, D,
|
||||
. ;or V options.
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
* Final processing of the DOS command.
|
||||
(A17A)
|
||||
TODOSCMD JSR DODOSCMD ;Go do the DOS command.
|
||||
|
||||
* Do the DOS command.
|
||||
(A180)
|
||||
DODOSCMD JSR RESTAT0 ;Zero out CONDNFLG and OPUTCOND.
|
||||
|
||||
* Reset CONDNFLG and OPUTCOND to zero.
|
||||
(A75B)
|
||||
RESTAT0 LDY #0
|
||||
STY CONDNFLG
|
||||
STY OPUTCOND
|
||||
(A763) RTS
|
||||
|
||||
* Zero out the FM parameter list so we
|
||||
* can customize it in accordance with the
|
||||
* specific DOS command about to be executed.
|
||||
(A183) JSR CLRFMPRM
|
||||
|
||||
* Clear out the FM parameter list.
|
||||
(A1AE)
|
||||
CLRFMPRM LDA #0
|
||||
LDY #$16
|
||||
ZFMPARM STA FMPRMLST-1,Y
|
||||
DEY
|
||||
BNE ZFMPARM
|
||||
(A1B8) RTS
|
||||
|
||||
* Do a "stack jump" to process the command.
|
||||
* (Note: THE COMMAND HANDLER IS ALWAYS
|
||||
* ENTERED WITH CONDNFLG & OPUTCOND = 0.)
|
||||
(A186) LDA NDX2CMD ;Get (a) = index to the command.
|
||||
TAX ;(x) = index to the table of entry points.
|
||||
LDA CMDTBL+1,X ;Get the address of the command handler
|
||||
PHA ;and put it on the stack (hi byte first).
|
||||
LDA CMDTBL,X
|
||||
PHA
|
||||
(A192) RTS ;Do a "stack jump" to the command handler.
|
||||
|
||||
********************************
|
||||
* *
|
||||
* Phony Command Handler *
|
||||
* *
|
||||
*------------------------------*
|
||||
|
||||
(----)
|
||||
CmdPhony .
|
||||
.
|
||||
.
|
||||
. ;Commands in which error can occur.
|
||||
. ;(Only includes commands that are shown in
|
||||
. ;their entirety in the formatted disassemblies.)
|
||||
. ;------------------------------------------------
|
||||
.
|
||||
(A7D0) JMP TYPMISM ;CMDOPEN, CMDBSAVE, CMDSAVE, CMDAPPND / CMDPOSN,
|
||||
. ;CMDWRITE, CMDREAD, CMDEXEC via CMDOPEN /
|
||||
. ;CMDINIT via CMDSAVE / CMDBRUN via CMDBLOAD.
|
||||
.
|
||||
.
|
||||
(----) JSR HNDLCMD
|
||||
|
||||
(A2A8)
|
||||
HNDLCMD .
|
||||
.
|
||||
.
|
||||
. ;Commands in which error can occur.
|
||||
. ;(Only includes commands that are shown in
|
||||
. ;their entirety in the formatted disassemblies.)
|
||||
. ;------------------------------------------------
|
||||
(A018) .
|
||||
PRSYNERR JMP SYNTXERR ;Detected a BSAVE cmd with no accompanying
|
||||
. ;A(ddress) or L(ength) parameters.
|
||||
.
|
||||
.
|
||||
(A2CF) JMP NOBUFERR ;CMDVERIFY, CMDLOCK, CMDUNLOK, CMDCATLG,
|
||||
. ;CMDRENAME, CMDELETE, CMDAPPND, CMDCHAIN,
|
||||
. ;CMDBSAVE, CMDBLOAD, CMDLOAD, CMDSAVE /
|
||||
. ;CMDBRUN via CMDBLOAD / CMDRUN via CMDLOAD /
|
||||
. ;CMDWRITE, CMDREAD, CMDEXEC or CMDPOSN via
|
||||
. ;CMDOPEN.
|
||||
.
|
||||
(A369) JMP TYPMISM ;CMDBLOAD or CMDBRUN via CMDBLOAD.
|
||||
.
|
||||
(A3A0) JMP TOOLARGE ;CMDSAVE and CMDINIT via CMDSAVE.
|
||||
.
|
||||
(A410) .
|
||||
TOTYPMIS JMP TYPMISM ;CMDCHAIN, CMDLOAD or CMDRUN via CMDLOAD.
|
||||
.
|
||||
.
|
||||
(A4AE) JMP TOOLARGE ;CMDCHAIN, CMDLOAD or CMDRUN via CMDLOAD.
|
||||
.
|
||||
(A5A5) .
|
||||
NOLNGINT LDA #1 ;CMDINT.
|
||||
(A5A7) JMP ERRHNDLR
|
||||
.
|
||||
(A63F) .
|
||||
ENDATERR LDA #5 ;CMDEXEC, CMDREAD or CMDPOSN.
|
||||
(A641) JMP ERRHNDLR
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
(A6A8) .
|
||||
FMDRIVER JSR FILEMGR
|
||||
|
||||
(AB06)
|
||||
FILEMGR TSX ;SAVE THE STACK POINTER so we can later
|
||||
STX STKSAV ;return to the caller of the file manager.
|
||||
JSR RSTRFMWA ;Copy work buf ---> FM work area.
|
||||
LDA OPCODEFM ;Check if the opcode is legal.
|
||||
CMP #13 ;(Must be less than 13.)
|
||||
BCS TOERROP ;Range error - opcode too large.
|
||||
ASL ;Double opcode val & put it in (x)
|
||||
TAX ;so it indexes the table of function adrs.
|
||||
LDA Phonyfunctbl+1,X ;Stick addr of function handler on
|
||||
PHA ;the stack (hi byte first) and then do a
|
||||
LDA Phonyfunctbl,X ; "stack jump" to the function
|
||||
PHA ;handler's entry point.
|
||||
(AB1E) RTS
|
||||
.
|
||||
.
|
||||
----------------------
|
||||
(AB1F)
|
||||
TOERROP JMP RNGERROP ;Normally can only occur if the file manager
|
||||
--------------------- ;is being used directly by custom assembly
|
||||
;language programs.
|
||||
.
|
||||
.
|
||||
(----) .
|
||||
FunctionPhony LDA SUBCODFM ;Check if subcode is legal.
|
||||
CMP #5 ;(Must be less than 5.)
|
||||
BCS TOERRSUB ;Error - illegal subcode.
|
||||
ASL ;Subcode * 2, cause 2 bytes per adr.
|
||||
TAX ;Index tbl of subfunction adrs.
|
||||
LDA Phonysubfunctbl,X ;Get addr (minus 1) of subfunction
|
||||
PHA ;entry point and stick it on the stack
|
||||
LDA Phonysubfunctbl,X ;(hi byte first).
|
||||
PHA
|
||||
(----) RTS ;Do a "stack jump" to the subfunction.
|
||||
.
|
||||
.
|
||||
----------------------
|
||||
(AC6A)
|
||||
TOERRSUB JMP RNGERRSB ;Normally, can only occur if the file
|
||||
--------------------- ;manager is being accessed by a custom
|
||||
;assembly language program and only if
|
||||
;the function being used requires a
|
||||
;subfunction.
|
||||
.
|
||||
.
|
||||
.
|
||||
(----) .
|
||||
SubfunctionPhony .
|
||||
.
|
||||
.
|
||||
. ;Functions in which error can occur.
|
||||
. ;(Only includes functions that are shown in
|
||||
. ;their entirety in the formatted
|
||||
. ;disassemblies.)
|
||||
. ;---------------------------------------
|
||||
.
|
||||
(AB5E) JMP LNGNOTAV ;FNOPEN, FNVERIFY, FNDELETE, FNRENAME,
|
||||
. ;FNLOCK and FNUNLOCK.
|
||||
.
|
||||
(AB61) .
|
||||
TOFILNOT JMP FILENOT ;FNOPEN, FNVERIFY, FNDELETE, FNRENAME,
|
||||
. ;FNLOCK and FNUNLOCK.
|
||||
.
|
||||
(AC6D) .
|
||||
TOFILOCK JMP FILELOKD ;FNRENAME.
|
||||
.
|
||||
(ACB8) .
|
||||
NDATERR JMP ENDOFDAT ;FNREAD.
|
||||
.
|
||||
.
|
||||
(AD36) JMP FILELOKD ;FNDELETE.
|
||||
.
|
||||
(B2C0) .
|
||||
TODSKFUL JMP DISKFULL ;FNOPEN.
|
||||
.
|
||||
.
|
||||
(B241) JMP DISKFULL ;FNOPEN, FNVERIFY, FNDELETE, FNRENAME,
|
||||
. ;FNLOCK and FNUNLOCK.
|
||||
.
|
||||
.
|
||||
.
|
||||
(----) JSR RWTSDRVR
|
||||
|
||||
(B052)
|
||||
RWTSDRVR STX IBTRK
|
||||
STY IBSECT
|
||||
RWTSDRV1 STA IBCMD
|
||||
(B058) .
|
||||
.
|
||||
.
|
||||
- finish setting up RWTS's
|
||||
input/output block (IOB).
|
||||
.
|
||||
.
|
||||
.
|
||||
(B08A) LDY ADRIOB ;Set (y) & (a) to
|
||||
LDA ADRIOB+1 ;pt at RWTS's IOB.
|
||||
(B090) JSR ENTERWTS ;Go call RWTS.
|
||||
|
||||
(B7B5)
|
||||
ENTERWTS PHP
|
||||
SEI
|
||||
JSR RWTS
|
||||
BCS ERRENTER
|
||||
PLP
|
||||
CLC
|
||||
(B7BE) RTS
|
||||
======
|
||||
|
||||
(B7BF)
|
||||
ERRENTER PLP
|
||||
SEC
|
||||
(B7C1) RTS
|
||||
======
|
||||
|
||||
(B093) .
|
||||
.
|
||||
.
|
||||
.
|
||||
(B09E) BCS ERRWTSDR ;Branch if UNsuccess.
|
||||
(B0A0) RTS
|
||||
============
|
||||
|
||||
* RWTS operation was NOT successful.
|
||||
* (Translate RWTS error code (a) to
|
||||
* an FM error code (y).)
|
||||
(B0A1)
|
||||
ERRWTSDR LDA IBSTAT
|
||||
LDY #7
|
||||
CMP #$20 ;Vol mismatch?
|
||||
BEQ SETFMERR ;Yes.
|
||||
LDY #$04
|
||||
CMP #$10 ;Write protected?
|
||||
BEQ SETFMERR ;Yes.
|
||||
LDY #$08 ;Must have been other,
|
||||
SETFMERR TYA ;so indicate I/O err.
|
||||
(B0B3) JMP BADFMXIT ;Go handle error.
|
||||
------------
|
||||
(B35F)
|
||||
LNGNOTAV LDA #1
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
RNGERROP LDA #2
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
RNGERRSB LDA #3
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
WRITPROT LDA #4
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
ENDOFDAT LDA #5
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
FILENOT LDA #6
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
DISKFULL JMP FULLPTCH
|
||||
NOP
|
||||
FILELOKD LDA #10
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 = signal good operation.
|
||||
BCC FMEXIT ;ALWAYS.
|
||||
BADFMXIT SEC ;(c) = 1 = signal unsuccessful operation.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0 ;Avoid that infamous $48 bug.
|
||||
STA STATUS
|
||||
JSR CPYFMWA ;Copy work area --> work buffer.
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;back from the stack.
|
||||
(B392) LDX STKSAV ;ADJUST THE STACK POINTER TO FORCE EXIT
|
||||
TXS ;TO THE CALLER EVEN IF SEVERAL SUBROUTINES
|
||||
(B396) RTS ;DEEPER THAN ORIGINAL ENTRY. (Always
|
||||
============ ;returns to the AFTRFUNC routine ($A6AB)
|
||||
;unless called by the RSETPTRS routine
|
||||
;($B6B3) which is used to exit the
|
||||
;append command handler. In this later
|
||||
;instance, STKSAV ($B39B) is reset to
|
||||
;exit the command before the FMEXIT
|
||||
;($B386) routine is entered.)
|
||||
|
||||
|
||||
* Disk-full-error patch.
|
||||
(BFED)
|
||||
FULLPTCH JSR CPYFMWA ;Copy work area --> work buffer.
|
||||
LDX STKSAV ;Reinstate the stk pointer so that CLOSEALL
|
||||
TXS ;($A316) sets STKSAV ($B39B) correctly.
|
||||
JSR CLOSEALL ;Close all the files.
|
||||
TSX ;Reset the stk pointer so we can return to
|
||||
STX STKSAV ;the AFTRFUNC routine ($A6AB) in FMDRIVER.
|
||||
LDA #9 ;Set (a) = disk-full error code.
|
||||
(BFFD) JMP BADFMXIT ;Go exit the error.
|
||||
------------
|
||||
|
||||
* Finish handling any function errors.
|
||||
* (Execution returns here because the
|
||||
* stack was reset with the value saved on
|
||||
* entry to the FMDRIVER routine ($A6A8).)
|
||||
* (If just read a byte from a data sector, enter
|
||||
* with a clear carry (even if byte was a $00).)
|
||||
(A6AB)
|
||||
AFTRFUNC BCC FMDRVRTN ;Branch if no errors.
|
||||
;If just did a read, branch if dealing
|
||||
;with a byte from a data sector (as opposed
|
||||
;to a byte from a T/S list).
|
||||
(A6AD) LDA RTNCODFM ;Get error code from FM parameter list.
|
||||
CMP #5 ;End-of-data error?
|
||||
(A6B2) BEQ TOAPPTCH ;Yes - not handled like other errors!!!.
|
||||
;File ends at a full data sec and so we
|
||||
;encountered a zeroed out T/S link or a
|
||||
;zeroed out data pair (trk/sec vals for
|
||||
;next data sec listed in T/S list).
|
||||
(A6B4) JMP OTHRERR ;Only take if got an error other than
|
||||
------------ ;an end-of-data error.
|
||||
|
||||
TOAPPTCH JMP APNDPTCH
|
||||
(A6B7) ------------
|
||||
|
||||
* Note: You are now entering an almost
|
||||
* undecipherable mess of spaghetti programming.
|
||||
* Parts of the following routines seem useless.
|
||||
* Some instruction may just represent residual (but
|
||||
* innocuous) bytes that are were left over from
|
||||
* an earlier version of DOS.
|
||||
|
||||
* Check if file pointer and WASTEBYT are zeroes.
|
||||
* (On entry, A4L/+1 is pointing at the FM work buffer.)
|
||||
(B692)
|
||||
APNDPTCH LDY #$13
|
||||
CK4ZEROS LDA (A4L),Y
|
||||
(B696) BNE SETAPFLG ;Unless we are dealing with a
|
||||
;useless file that was previously
|
||||
;opened, but never closed, this
|
||||
;instruction is always taken.
|
||||
(B698) INY
|
||||
CPY #$17
|
||||
(B69B) BNE CK4ZEROS
|
||||
|
||||
* The purpose of the following instructions is not
|
||||
* understood. This section of code may have been
|
||||
* designed to deal with useless files that were
|
||||
* opened but never closed. Whatever, the original
|
||||
* purpose was, the following code appears to keep
|
||||
* the file pointer at #$000000 when a file with no
|
||||
* data is encountered.
|
||||
* (On entry, A4L/+1 is pointing at the FM work buffer.)
|
||||
(B69D) LDY #$19
|
||||
COPYRECS LDA (A4L),Y ;Copy image of RECNMNWA/+1 and BYTOFFWA/+1
|
||||
STA RECNMBFM-$19,Y ;that were just stored in the work
|
||||
INY ;buffer to RECNMBFM/+1 and BYTOFFFM/+1
|
||||
CPY #$1D ;in the FM parm list.
|
||||
BNE COPYRECS
|
||||
FMDVRTN JMP BK2FMDRV
|
||||
(B6A9) ------------
|
||||
|
||||
* Set the append flag.
|
||||
* (Never entered if dealing
|
||||
* with an empty file.)
|
||||
(B6AC)
|
||||
SETAPFLG LDX #$FF
|
||||
STX APPNDFLG ;Set the append flag.
|
||||
(B6B1) BNE FMDVRTN ;ALWAYS.
|
||||
------------
|
||||
|
||||
(A6BA) NOP
|
||||
BK2FMDRV JSR CKIFAPND
|
||||
(A6BB)
|
||||
|
||||
* Check if using APPEND command.
|
||||
(BA69)
|
||||
CKIFAPND LDX CMDINDEX ;Get command index.
|
||||
CPX #$1C ;Are we APPENDing?
|
||||
BEQ RTNCKAPN ;Yes leave flag on.
|
||||
LDX #0 ;No - turn off append flag.
|
||||
STX APPNDFLG
|
||||
RTNCKAPN RTS
|
||||
(BA75)
|
||||
|
||||
(A6BE) LDX #0 ;Zero out the "one-data byte" parameter in FM parm list.
|
||||
STX ONEIOBUF ;(Also referred to as low byte of CURIOBUF.)
|
||||
FMDRVRTN RTS ;Return to caller of FMDRIVER.
|
||||
(A6C3) ============
|
||||
|
||||
|
||||
* Error was deadly so we better
|
||||
* release the file's buffer and
|
||||
* make sure the append flag is off.
|
||||
(B65E)
|
||||
OTHRERR JSR GETBUFF ;Locate buffer belonging to the file.
|
||||
;(Put addr of buf in A3L/+1.)
|
||||
(B661) BCS TOERRMSG ;No buffer was assigned so no need to
|
||||
;release file's buf or turn off append
|
||||
;flag.
|
||||
(B663) LDA #0 ;Zero out the append flag and set
|
||||
TAY ;(y) to index the first byte of the
|
||||
STA APPNDFLG ;DOS name buf.
|
||||
STA (A3L),Y ;Release the file's DOS buffer.
|
||||
TOERRMSG LDA RTNCODFM ;Get error code so can index err msg.
|
||||
(B66E) JMP ERRHNDLR ;Exit and do error message.
|
||||
------------
|
||||
|
||||
(A6C4)
|
||||
SYNTXERR LDA #11
|
||||
BNE ERRHNDLR ;ALWAYS.
|
||||
NOBUFERR LDA #12
|
||||
BNE ERRHNDLR ;ALWAYS.
|
||||
TOOLARGE LDA #14
|
||||
BNE ERRHNDLR ;ALWAYS.
|
||||
TYPMISM LDA #13
|
||||
(A6D0)
|
||||
|
||||
(A6D2)
|
||||
ERRHNDLR STA ASAVED ;Save error code for later use.
|
||||
(A6D5) JSR RESTATIN
|
||||
|
||||
* Patch to set condition 0 and
|
||||
* clear the run interrupt flag.
|
||||
(BFE6)
|
||||
RESTATIN JSR RESTAT0
|
||||
|
||||
* Reset CONDNFLG & OPUTCOND to zero.
|
||||
(A75B)
|
||||
RESTAT0 LDY #0
|
||||
STY CONDNFLG
|
||||
STY OPUTCOND
|
||||
(A763) RTS
|
||||
|
||||
(BFE9) STY RUNTRUPT ;Clear the run interrupt flag.
|
||||
(BFEC) RTS
|
||||
|
||||
(A6D8) LDA ACTBSFLG ;Check if Integer or FP basic is active.
|
||||
(A6DB) BEQ WASINT ;Branch if using Integer.
|
||||
;(On-error flag not applicable to integer.)
|
||||
(A6DD) LDA ERRFLG ;Check if basic's ONERR flag is on.
|
||||
(A6DF) BMI ONERRACT ;Yes - skip printing of error message
|
||||
;cause we eventually want to go to our
|
||||
(A6E1) ;own custom BASIC error handling routine.
|
||||
WASINT LDX #0 ;Initialize index to tbl of offsets to errs.
|
||||
(A6E3) JSR PRDOSERR ;Go print: <rtn>, <bell>, <rtn>.
|
||||
|
||||
* Print the DOS error message.
|
||||
(A702)
|
||||
PRDOSERR LDA OFF2ERR,X ;Use the error code to get an offset to
|
||||
;the error message.
|
||||
(A705) TAX ;(x) = offset to table of err msg text.
|
||||
MOREMSG STX TEMPBYT ;Save offset to text.
|
||||
LDA ERRTXTBL,X ;Get an error-message character.
|
||||
PHA ;Save it on the stack.
|
||||
ORA #$80 ;Turn the hi bit on to satisfy monitor.
|
||||
(A70F) JSR GODSPLY
|
||||
|
||||
* Character output handler.
|
||||
(9FC5)
|
||||
GODSPLY JMP (CSW) ;Pts 2 true hndlr.
|
||||
------------
|
||||
|
||||
* Monitor ROM's output char handler.
|
||||
(FDF0)
|
||||
COUT1 .
|
||||
.
|
||||
(See dis'mbly in APPLE II REFERENCE MANUAL.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(A712) LDX TEMPBYT ;Reset (x) = offset to tbl of err msg text.
|
||||
INX ;Kick index up for next char of message.
|
||||
PLA ;Get original char back in (a).
|
||||
BPL MOREMSG ;Branch if more chars in message.
|
||||
(A719) RTS ;(All but the last char in @ msg are pos.)
|
||||
|
||||
(A6E6) LDX ASAVED ;Get saved return code.
|
||||
JSR PRDOSERR ;Go print the error message.
|
||||
;(See dis'mbly above.)
|
||||
(A6EC) JSR CRVIADOS ;Print a <cr> via DOS & monitor ROM.
|
||||
|
||||
* Print a carriage return.
|
||||
(9FC8)
|
||||
CRVIADOS LDA #$8D ;<cr>.
|
||||
(9FCA) JMP GODSPLY ;Go print it.
|
||||
------------
|
||||
|
||||
* Character output handler.
|
||||
(9FC5)
|
||||
GODSPLY JMP (CSW) ;Pts 2 true hndlr.
|
||||
------------
|
||||
|
||||
* Monitor ROM's output char handler.
|
||||
(FDF0)
|
||||
COUT1 .
|
||||
.
|
||||
(See dis'mbly in APPLE II REFERENCE MANUAL.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(A6EF)
|
||||
ONERRACT JSR INITIOHK ;Reset the I/O hooks to point to DOS.
|
||||
|
||||
* Initialize the I/O hooks so that DOS intercepts
|
||||
* all input & output. For instance, if a routine
|
||||
* encounters a "COUT JMP (CSW)", then execution will
|
||||
* actually flow to DOS's output routine (OPUTINCP,
|
||||
* $9EBD). Similarly, any routine that refers to
|
||||
* "RDKEY JMP (KSW)" will actually jump to DOS's
|
||||
* input routine (INPTINCP, $9E81).
|
||||
*
|
||||
* The true (ie. normal) hooks are saved, ex:
|
||||
* KSW: KEYIN --> KSWTRUE: KEYIN.
|
||||
* CSW: COUT1 --> CSWTRUE: COUT1.
|
||||
* The intercepts are then set as follows:
|
||||
* ADINPTCP: INPTINCP --> KSW: INPTINCP.
|
||||
* ADOPUTCP: OPUTINCP --> CSW: OPUTINCP.
|
||||
|
||||
* Check if the input hook needs to be reset.
|
||||
(A851)
|
||||
INITIOHK LDA KSW+1
|
||||
CMP ADINPTCP+1
|
||||
(A856) BEQ CKOUTHK ;Input hook already points to DOS's
|
||||
;input handler, so go check output hook.
|
||||
|
||||
* Reset the input hook to point to DOS.
|
||||
(A858) STA KSWTRUE+1 ;KSW: KEYIN --> KSWTRUE: KEYIN.
|
||||
LDA KSW
|
||||
STA KSWTRUE
|
||||
LDA ADINPTCP ;ADINPTCP: INPTINCP --> KSW: INPTINCP.
|
||||
STA KSW
|
||||
LDA ADINPTCP+1
|
||||
(A868) STA KSW+1
|
||||
|
||||
* Check if the output hook needs to be reset.
|
||||
(A86A)
|
||||
CKOUTHK LDA CSW+1
|
||||
CMP ADOPUTCP+1
|
||||
(A86F) BEQ SETHKRTN ;Output hook already points to DOS's
|
||||
;output handler, so go exit.
|
||||
|
||||
* Reset the output hook to point to DOS.
|
||||
(A871) STA CSWTRUE+1,X ;CSW: COUT1 --> CSWTRUE: COUT1.
|
||||
LDA CSW
|
||||
STA CSWTRUE
|
||||
LDA ADOPUTCP ;ADOPUTCP: OPUTINCP --> CSW: OPUTINCP.
|
||||
STA CSW
|
||||
LDA ADOPUTCP+1
|
||||
STA CSW+1
|
||||
SETHKRTN RTS
|
||||
(A883)
|
||||
|
||||
(A6F2) JSR CKBSCRUN ;Check if basic is running a program.
|
||||
|
||||
* Is a version of basic running?
|
||||
(A65E)
|
||||
CKBSCRUN PHA ;Save (a) on the stack.
|
||||
LDA ACTBSFLG ;Which basic is up?
|
||||
(A662) BEQ INTBASIC ;Branch if using integer.
|
||||
|
||||
* Using Applesoft - now if the line number
|
||||
* is greater than 65288 ($FF in hi byte),
|
||||
* then we are using the immediate mode.
|
||||
(A664) LDX CURLIN+1 ;Check hi byte of line number.
|
||||
INX ;If $FF --> $00, then # > 65288.
|
||||
(A667) BEQ IMEDMODE ;Branch if using immediate mode.
|
||||
|
||||
* FP apprears to be running a program.
|
||||
* But, maybe CURLIN+1 was zapped, so
|
||||
* also check the prompt.
|
||||
(A669) LDX PROMPT ;Are we using an RH bracket (ie. an
|
||||
CMP #$DD ;Applesoft prompt)?
|
||||
(A66D) BEQ IMEDMODE ;Yes - so must be in immediate mode.
|
||||
|
||||
(A66F)
|
||||
RUNNING PLA ;Get saved (a) back from the stack.
|
||||
CLC ;Signal program is running.
|
||||
(A671) RTS
|
||||
============
|
||||
|
||||
(A672)
|
||||
INTBASIC LDA RUNMODE ;Check Integer basic's run mode flag.
|
||||
(A674) BMI RUNNING ;If neg, Integer basic is in deferred.
|
||||
|
||||
(A676)
|
||||
IMEDMODE PLA ;Get save (a) back from the stack.
|
||||
SEC ;Signal that we're in the immediate mode.
|
||||
(A678) RTS
|
||||
============
|
||||
|
||||
(A6F5) LDX ASAVED ;Get the saved return code.
|
||||
(A6F8) LDA #3 ;Set (a) = 3 in case we fall thru to go to
|
||||
;basic's error handling routine. (The magic
|
||||
;number of "3" allows BSCERHLR ($D865) to
|
||||
;condition (c) = 1 and (z) = 1 to comply with
|
||||
;the basic routine that is responsible for
|
||||
;printing basic's error messages.)
|
||||
(A6FA) BCS DOWRM ;Basic is not running.
|
||||
TOBSCERR JMP (ADBSCERR) ;Jump to basic's error handling routine
|
||||
(A6FC) ------------ ;(BSCERHLR, $D865). (ADBSCERR EQU $9D5A).
|
||||
DOWRM JMP (TOWRMVEC) ;Jump to basic's warmstart routine
|
||||
(A6FF) ------------ ;(RESTART, $D43C). (TOWRMVEC EQ $9D5E).
|
||||
|
||||
|
||||
* Table of offsets used to index the error
|
||||
* message text table ($AA3F - $AA4E).
|
||||
* (Hackers often swap these bytes around so
|
||||
* erroneous error messages will be used.)
|
||||
(AA3F)
|
||||
OFF2ERR HEX 00 ;Error code - 0
|
||||
HEX 03 ; - 1
|
||||
HEX 19 ; - 2
|
||||
HEX 19 ; - 3
|
||||
HEX 24 ; - 4
|
||||
HEX 33 ; - 5
|
||||
HEX 3E ; - 6
|
||||
HEX 4C ; - 7
|
||||
HEX 5B ; - 8
|
||||
HEX 64 ; - 9
|
||||
HEX 6D ; - 10
|
||||
HEX 78 ; - 11
|
||||
HEX 84 ; - 12
|
||||
HEX 98 ; - 13
|
||||
HEX AA ; - 14
|
||||
(AA4E) HEX BB ; - 15
|
||||
|
||||
|
||||
* Text table of DOS error messages ($A971 - $AA3E).
|
||||
* These messages are frequently altered in commerical
|
||||
* programs. (Note that only the last character of each
|
||||
* text message is written in negative ASCII form. Also
|
||||
* note that error codes 11 to 15 are NOT set when DOS
|
||||
* is accessed via indirect calls to the file manager.)
|
||||
(A971) ; Corresponding error code & address.
|
||||
ERRTXTBL HEX 0D078D ; 0 ($A971 - $A973)
|
||||
;<cr>, <bell>, <cr>.
|
||||
DCI 'LANGUAGE NOT AVAILABLE' ;1 ($A974 - $A989)
|
||||
DCI 'RANGE ERROR' ; 2 & 3 ($A98A - $A994)
|
||||
;Bad FM opcode or subcode or else,
|
||||
;got illegal arguments issued for IN#,
|
||||
;PR#, MAXFILES cmds or for A, B, R, L,
|
||||
;S, D, V, C, I or O options.
|
||||
DCI 'WRITE PROTECTED' ; 4 ($A995 - $A9A3)
|
||||
DCI 'END OF DATA' ; 5 ($A9A4 - $A9AE)
|
||||
DCI 'FILE NOT FOUND' ; 6 ($A9AF - $A9BC)
|
||||
DCI 'VOLUME MISMATCH' ; 7 ($A9BD - $A9CB)
|
||||
DCI 'I/O ERROR' ; 8 ($A9CC - $A9D4)
|
||||
DCI 'DISK FULL' ; 9 ($A9D5 - $A9DD)
|
||||
DCI 'FILE LOCKED' ; 10 ($A9DE - $A9E8)
|
||||
DCI 'SYNTAX ERROR' ; 11 ($A9E9 - $A9F4)
|
||||
DCI 'NO BUFFERS AVAILABLE' ; 12 ($A9F5 - $AA08)
|
||||
DCI 'FILE TYPE MISMATCH' ; 13 ($AA09 - $AA1A)
|
||||
DCI 'PROGRAM TOO LARGE' ; 14 ($AA1B - $AA2B)
|
||||
DCI 'NOT DIRECT COMMAND' ; 15 ($AA2C - $AA3D)
|
||||
(AA3E) HEX 8D ;<CR> no code ($AA3E)
|
||||
|
||||
|
1348
textfiles.com/apple/ANATOMY/doscoldstart.txt
Normal file
1348
textfiles.com/apple/ANATOMY/doscoldstart.txt
Normal file
File diff suppressed because it is too large
Load Diff
1243
textfiles.com/apple/ANATOMY/doswarmstart.txt
Normal file
1243
textfiles.com/apple/ANATOMY/doswarmstart.txt
Normal file
File diff suppressed because it is too large
Load Diff
2252
textfiles.com/apple/ANATOMY/file.manager.s.txt
Normal file
2252
textfiles.com/apple/ANATOMY/file.manager.s.txt
Normal file
File diff suppressed because it is too large
Load Diff
653
textfiles.com/apple/ANATOMY/fn.lock.unlock.txt
Normal file
653
textfiles.com/apple/ANATOMY/fn.lock.unlock.txt
Normal file
@@ -0,0 +1,653 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* LOCK AND UNLOCK *
|
||||
* Function Handlers *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* The LOCK and UNLOCK function handlers ($ACEF & $ACF6) *
|
||||
* set the lock/unlock mask (LOKUNMSK, $B39E) with $80 (lock) *
|
||||
* or $00 (unlock) and the call the COMNOPEN routine ($AB28) *
|
||||
* to locate the desired file. COMNOPEN configures the FM work *
|
||||
* area and then searches the directory sectors for a file *
|
||||
* description containing the name of the wanted file. (The *
|
||||
* links to the first directory sector are housed in the VTOC. *
|
||||
* Each subsequent directory contains the links to the next *
|
||||
* directory sector. The link bytes of the last directory sector *
|
||||
* are zeroed out.) *
|
||||
* Each directory contains up to seven different file *
|
||||
* descriptions. An example of the information contained in a *
|
||||
* file description is shown below: *
|
||||
* FIL1TSTK DS 1 ;Track # of first T/S list for file 1. *
|
||||
* FIL1TSSC DS 1 ;Sector # of first T/S list for file 1. *
|
||||
* FIL1TYPE DS 1 ;File type code for file 1. ($00=Text, *
|
||||
* ;$01=Integer, $02=Applesoft, $04=Binary, *
|
||||
* ;$08=S-type, $10=Relocatable, $20=A-type *
|
||||
* ;and $40=B-type.) The hi bit is set on *
|
||||
* ;locked files. For example, $02=unlocked *
|
||||
* ;Applesoft and $82=locked Applesoft. *
|
||||
* FIL1NAME DS 30 ;Name of file 1. If a file name less than *
|
||||
* ;30 bytes is used, trailing spaces are *
|
||||
* ;added to the name to fill the buffer. *
|
||||
* FIL1SIZE DS 2 ;Size of file 1 in terms of the number of *
|
||||
* ;sectors used. *
|
||||
* (If a file was deleted, the track # of the file's first T/S *
|
||||
* list was copied to the last byte position of the name field. *
|
||||
* The original track # byte (FIL1TSTK) was then overwritten with *
|
||||
* an #$FF.) *
|
||||
* As each directory sector is read in, an attempt is made *
|
||||
* to locate a file description which contains the name of the *
|
||||
* file wanted. If the name can't be located after searching all *
|
||||
* the directories, a second search is made to locate the first *
|
||||
* available space in a directory sector where a new file *
|
||||
* description can be placed (in case the command can create a *
|
||||
* new file). If no free space is located, a disk-full error *
|
||||
* message is printed. *
|
||||
* If an available space is located, NEWDSCRP ($B2C1) copies *
|
||||
* the name of the wanted file from the primary file name buffer *
|
||||
* (PRIMFNBF, $AA75) into the new entry space. A check is then *
|
||||
* made to see if the command can legally create a new file. The *
|
||||
* identifying command byte (NDX2CMD, $AA5F) is used to index a *
|
||||
* table of command attributes (CMDATTRB, $A909). Because bit0 *
|
||||
* of the first attribute bytes of both the LOCK and UNLOCK *
|
||||
* commands are clear, neither command can create a new file. As *
|
||||
* a result, the LOCK or UNLOCK commands are exited with a file- *
|
||||
* not-found error. *
|
||||
* If a (non-deleted) description entry containing the name *
|
||||
* of the wanted file is located, execution branches to the *
|
||||
* FILLINWA routine ($ABA6). FILLINWA uses the information *
|
||||
* contained in the description entry to customize the FM work *
|
||||
* area. Eventhough it is not needed for either the LOCK or *
|
||||
* UNLOCK functions, the first T/S list belonging to the wanted *
|
||||
* file is read in (READTS, $A5FE). *
|
||||
* Next, the accumulator is loaded with the file type code *
|
||||
* from the file description. The hi bit of the code is dropped *
|
||||
* by ANDing the accumulator with #$7F. The result is then *
|
||||
* merged with the LOKUNMSK to set (lock) or clear (unlock) the *
|
||||
* hi bit. Finally, the updated file type code is put back into *
|
||||
* the file description. *
|
||||
* After WRDIRECT ($B037) is called to write the modified *
|
||||
* directory sector back to the disk, execution returns to the *
|
||||
* LOCK or UNLOCK command handler. *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
* Lock Function Handler.
|
||||
(ACEF)
|
||||
FNLOCK LDA #$80 ;Set hi bit in lock/unlock mask.
|
||||
STA LOKUNMSK
|
||||
(ACF4) BNE COMNLOCK ;ALWAYS.
|
||||
|
||||
Unlock Function Handler.
|
||||
(ACF6)
|
||||
FNUNLOCK LDA #0 ;Make sure hi bit is clear in the LOKUNMSK.
|
||||
(ACF8) STA LOKUNMSK
|
||||
|
||||
* Routine common to lock/unlock functions.
|
||||
(ACFB)
|
||||
COMNLOCK JSR COMNOPEN ;Locate a file with the same name & open it.
|
||||
|
||||
*** NOTE ***
|
||||
* Not all of the common open routine is
|
||||
* listed below because not all of it
|
||||
* applies to the lock/unlock functions.
|
||||
|
||||
* Common open routine.
|
||||
(AB28)
|
||||
COMNOPEN JSR ZWRKAREA ;Initialize the work area.
|
||||
|
||||
* Zero out the FM work area so it can be customized
|
||||
* in accordance with the calling function.
|
||||
* (Although some work bytes may not be subsequently
|
||||
* altered, don't be lulled into thinking that they
|
||||
* are not important. Zero values are just as relevant
|
||||
* as non-zero values.)
|
||||
* (P.S. Don't confuse the FM work area with its image
|
||||
* (FM work buffer) that is housed in the chain of
|
||||
* DOS buffers.)
|
||||
(ABDC)
|
||||
ZWRKAREA LDA #0
|
||||
TAX ;Initialize the x-index.
|
||||
ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
|
||||
INX
|
||||
CPX #45 ;Work area is 45 bytes long.
|
||||
(ABE5) BNE ZEROWRKA
|
||||
|
||||
* Begin customizing the work area.
|
||||
* Get volume, drive, slot & catalog track
|
||||
* values from the FM parameter list. Put
|
||||
* drive, slot*16, catalog track and
|
||||
* complemented volume number in the work area.
|
||||
(ABE7) LDA VOLFM ;Volume number.
|
||||
EOR #$FF ;Calculate 1's complement of volume #.
|
||||
STA VOLWA
|
||||
LDA DRVFM ;Drive #.
|
||||
STA DRVWA
|
||||
LDA SLOTFM ;Get slot #.
|
||||
ASL ;Calculate slot * 16.
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
TAX ;Set (x) = slot * 16.
|
||||
STX SLOT16WA
|
||||
LDA #$11 ;Normal catalog trk = #17.
|
||||
STA TRKWA
|
||||
(AC05) RTS
|
||||
|
||||
(AB2B) LDA #1 ;Describe sector length as 256 bytes
|
||||
(AB2D) STA SECSIZWA+1 ;(in the FM work area).
|
||||
|
||||
* Get record length from the FM parameter
|
||||
* list & put it in the FM work area.
|
||||
* (Don't allow a zero length. If zero,
|
||||
* change it to one.)
|
||||
(AB30) LDX RECLENFM+1
|
||||
LDA RECLENFM
|
||||
BNE STRECLEN ;Non-zero record length is ok.
|
||||
CPX #0
|
||||
BNE STRECLEN
|
||||
INX ;Was zero, make it one instead.
|
||||
STRECLEN STA RECLENWA ;Put length in FM work area.
|
||||
STX RECLENWA+1
|
||||
(AB43) JSR GETFNTRY ;Try to find a directory sector for the file.
|
||||
|
||||
* Locate or create a file entry in the
|
||||
* directory buffer.
|
||||
* Make two searches if necessary:
|
||||
* - Search1 - try to locate entry with same name as file wanted.
|
||||
* - Search2 - couldn't locate entry corresponding to file
|
||||
* wanted so create a new entry in first available
|
||||
* space in the directory sector.
|
||||
(B1C9)
|
||||
GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to
|
||||
;TRKMAPS & to the first directory sector.
|
||||
|
||||
* Read the Volume Table of Contents (VTOC).
|
||||
(AFF7)
|
||||
READVTOC LDA #1 ;Read opcode for RWTS.
|
||||
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
||||
|
||||
* Code common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
||||
STY IBBUFP ;FM constants table & designate it
|
||||
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
||||
LDY #0 ;to the trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dism'bly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Point A4L/H at the primary file name buffer.
|
||||
(B1CC) LDA FNAMBUFM ;Get address of the name buffer from the
|
||||
STA A4L ;FM parameter list & put it in the A4L/H
|
||||
LDA FNAMBUFM+1 ;pointer.
|
||||
(B1D4) STA A4L+1
|
||||
|
||||
* Try to find the directory sector with the
|
||||
* wanted file name & read it into the directory
|
||||
* sector buffer. Make two searches if necessary.
|
||||
* On the first search, try to find a matching name.
|
||||
* If that doesn't work, do a second search to store
|
||||
* the description in the first available file
|
||||
* description field in a directory sector.
|
||||
(B1D6) LDA #1 ;Initialize the search counter (SCRNSRCH)
|
||||
SETSRCH STA SCRNSRCH ;in the FM scratch space for two searches.
|
||||
(B1D8) ;(1 = search1, 0 = search2)
|
||||
(B1DB) LDA #0 ;Initialize offset of file description from
|
||||
STA SECNXDIR ;the very first directory sector.
|
||||
CLC ;(c)=0=signal to read first directory sec.
|
||||
GETDIRSC INC SECNXDIR ;Kick up offset from first directory.
|
||||
(B1E4) JSR RDDIRECT ;Go read directory sector into buffer.
|
||||
|
||||
* Read a directory sector.
|
||||
(B011)
|
||||
RDDIRECT PHP ;Save (c) on stack:
|
||||
; (c) = 0 = read 1rst directory sector.
|
||||
; (c) = 1 = read next directory sector.
|
||||
(B012) JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get addr of direc
|
||||
STA IBBUFP ;sec buf from the
|
||||
LDA ADRDIRBF+1 ;FM constants tbl
|
||||
STA IBBUFP+1 ;& designate it as
|
||||
(B051) RTS ;as the I/O buffer.
|
||||
|
||||
(B015) PLP ;Check if 1rst directory sec or not.
|
||||
(B016) BCS RDNXTDIR ;Go read next directory sector.
|
||||
|
||||
* Read the first directory sector.
|
||||
* (Carry = 0.)
|
||||
(B018)
|
||||
RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory
|
||||
LDX FIRDIRTK ;sector (from the VTOC buffer).
|
||||
(B01E) BNE DODIRRD ;ALWAYS - go read in directory sector.
|
||||
|
||||
* Read the next directory sector.
|
||||
* (Carry = 1.)
|
||||
(B020)
|
||||
RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
(B023) BNE GETDIRLK ;Link not zeroed out.
|
||||
SEC ;Link zeroed out - exit with (c) = 1 to
|
||||
(B026) RTS ;signal there are no more directory secs.
|
||||
=============
|
||||
|
||||
(B027)
|
||||
GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
|
||||
* Call to read in the directory sector.
|
||||
(B02A)
|
||||
DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that
|
||||
(B02D) STY CURDIRSC ;we are about to read so they will be
|
||||
;the current directory sec values for the
|
||||
;next time around.
|
||||
(B030) LDA #1 ;Read opcode for RWTS.
|
||||
(B032) JSR RWTSDRVR ;Call RWTS driver to do the read.
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B035) CLC ;Link didn't zero out so signal that there
|
||||
(B036) RTS ;are more directory secs to read & exit.
|
||||
============
|
||||
|
||||
(B1E7) BCS CHNGSRCH ;Link zeroed out, no more directory secs,
|
||||
;so go switch searches.
|
||||
(B1E9) LDX #0
|
||||
CKDIRTRK STX CURDIRNX ;Offset of file description into the current
|
||||
(B1EB) ;directory sector.
|
||||
(B1EF) LDA FIL1TSTK,X ;Get track number of first T/S list
|
||||
;for a particular file from the file
|
||||
;description entry in the directory sector.
|
||||
(B1F1) BEQ CHRSRCHA ;If trk=0, no more files in this direc sec.
|
||||
(B1F3) BMI CHRSRCHB ;Skip deleted file. (When a file is
|
||||
;deleted, #$FF is put in byte where trk #
|
||||
;of first T/S list is usually kept.
|
||||
|
||||
* Compare the name found in the file
|
||||
* description entry portion of the
|
||||
* directory sector with the file name
|
||||
* wanted. (On entry, A4L/H points at
|
||||
* the primary file name buffer.)
|
||||
(B1F5) LDY #0 ;Initialize index to file name buffer.
|
||||
INX ;Point (x) at the first char position
|
||||
INX ;in the name field of description entry.
|
||||
CMPNAMES INX
|
||||
LDA (A4L),Y ;Get char of name from primary.
|
||||
CMP FIL1TSTRK,X ;Compare to char in name in description.
|
||||
BNE DONTMTCH ;Chars (and therefore names) don't match.
|
||||
INY
|
||||
CPY #30 ;Done all chars yet (0 to 29)?
|
||||
BNE CMPNAMES ;Chars matched, branch if more to check.
|
||||
LDX CURDIRNX ;All chars matched, so names matched.
|
||||
CLC ;Return with (x) = index to file
|
||||
(B20A) RTS ;description in current directory sector
|
||||
============ ;and with (c) = 0 to signal that the
|
||||
;correct file description was found.
|
||||
|
||||
* Advance index to point at the next
|
||||
* potential file description entry.
|
||||
(B20B)
|
||||
DONTMTCH JSR NXPLUS35 ;Names didn't match, so adjust index
|
||||
;to point at the next entry.
|
||||
|
||||
* Add 35 to the offset to point the index
|
||||
* at the next file description entry.
|
||||
* (Check to make sure that we don't index
|
||||
* right off the end of the directory sec.)
|
||||
(B230)
|
||||
NXPLUS35 CLC
|
||||
LDA CURDIRNX
|
||||
(B234) ADC #35 ;Add 35 to index. (Each file description
|
||||
;entry is 35 bytes long.)
|
||||
(B236) TAX ;Check if there is more space for entries
|
||||
CPX #245 ;in the current directory sector.
|
||||
(B239) RTS ;Exit with (c) conditioned:
|
||||
; (c) = 0 = more space in directory.
|
||||
; (c) = 1 = ran off end of directory.
|
||||
|
||||
(B20E) BCC CKDIRTRK ;More potential file descriptions to check
|
||||
;in this directory sector.
|
||||
(B210) BCS GETDIRSC ;Go get next directory sector.
|
||||
------------
|
||||
|
||||
* If we just completed first search,
|
||||
* go back to do second search.
|
||||
(B212)
|
||||
CHRSRCHA LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B215) BNE SETSRCH ;Go switch to second search.
|
||||
|
||||
* If first search, skip deleted files.
|
||||
* If second search, fall through to store
|
||||
* the description in the first unused
|
||||
* space in the directory.
|
||||
(B217)
|
||||
CHRSRCHB LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B21A) BNE DONTMTCH
|
||||
|
||||
* Couldn't locate the named file in the
|
||||
* directory description entries, so begin
|
||||
* creating a new description in the first available
|
||||
* space in a directory (in case command can
|
||||
* legally create a new file).
|
||||
(B21C)
|
||||
NWDESCRP LDY #0 ;Initialize index to primary file name buffer.
|
||||
INX ;Set index to first char position in the
|
||||
INX ;name field of the file description entry
|
||||
SETNWNAM INX ;space in the directory sector.
|
||||
LDA (A4L),Y ;Copy char from primary file name buffer
|
||||
STA FIL1TSTK,X ;to the directory description space.
|
||||
INY
|
||||
CPY #30 ;30 chars in name (0 to 29).
|
||||
BNE SETNWNAM ;Branch if more chars to copy.
|
||||
LDX CURDIRNX ;Return with (x) = index to file
|
||||
SEC ;description space in current directory
|
||||
(B22F) RTS ;sector & with (c)=1 to signal new entry
|
||||
============ ;was just created.
|
||||
|
||||
* If first search, switch to second search.
|
||||
* If second search, link zeroed out because
|
||||
* there isn't enough room left on the
|
||||
* disk for a new entry. Therefore,
|
||||
* exit with a disk-full error message.
|
||||
(B23A)
|
||||
CHNGSRCH LDA #0 ;Used to reset the search counter if
|
||||
;go back to start a second search.
|
||||
(B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
BNE SETSRCH ;Just did 1rst search so go start 2nd search.
|
||||
(B241) JMP DISKFULL ;Even second search was unsuccesful so go
|
||||
------------ ;handle a disk-full error.
|
||||
|
||||
(AB46) BCC FILLINWA ;Branch if found a directory sector with
|
||||
;name wanted in the file description entry.
|
||||
|
||||
* Named file wasn't found in directory,
|
||||
* so prepare a new file entry in case
|
||||
* command can legally create a new file.
|
||||
(AB48) STX CURDIRNX ;Offset to new description entry in
|
||||
;case want to create a new file.
|
||||
|
||||
* Check to see if command can
|
||||
* legally create a new file.
|
||||
(AB4B) LDX NDX2CMD ;(x) = index representing command.
|
||||
(AB4E) LDA CMDATTRB,X ;Get first byte containing description
|
||||
;of the given command's attributes.
|
||||
(AB51) LDX CURDIRNX ;(x) = index for new file description
|
||||
;entry into the directory sector.
|
||||
(AB54) LSR ;(c) = bit 0 of 1rst attribute byte.
|
||||
(AB55) BCS CREATNEW ;If (c) = 1, command can create a new file.
|
||||
;ALWAYS FALL THRU FOR LOCK/UNLOCK FUNCTIONS (cause (c) = 0).
|
||||
|
||||
* Command can't create a new file.
|
||||
* See which language we are using and
|
||||
* exit with the appropriate error msg.
|
||||
(AB57)
|
||||
NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM),
|
||||
;$80=coldstart & $C0=integer.
|
||||
(AB5A) CMP #$C0 ;Integer in ROM?
|
||||
BNE TOFILNOT ;No.
|
||||
(AB5E) JMP LNGNOTAV ;Yes - handle language-not-available error.
|
||||
------------
|
||||
|
||||
TOFILNOT JMP FILENOT ;Handle file-not-found error.
|
||||
(AB61) ------------
|
||||
|
||||
**************** NOTE *************************
|
||||
* Although it is not needed for the lock/unlock
|
||||
* functions, the first T/S list sector is automatically
|
||||
* read into the T/S list buffer (in chain) if the
|
||||
* file was found.
|
||||
|
||||
* Fill in the FM work area buffer.
|
||||
* (Routine common to opening a new
|
||||
* or pre-existing file.)
|
||||
(ABA6)
|
||||
FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec).
|
||||
STA FIRSTSTK
|
||||
LDA FIL1TSSC,X ;T/S list sec val (from directory sec).
|
||||
STA FIRTSSEC
|
||||
LDA FIL1TYPE,X ;File type (from directory sec).
|
||||
STA FILTYPFM
|
||||
STA FILTYPWA
|
||||
LDA FIL1SIZE,X ;File size (from directory sec).
|
||||
STA FILENSEC
|
||||
LDA FIL1SIZE+1,X
|
||||
STA FILENSEC+1
|
||||
STX BYTNXDIR ;Index into directory sec to description.
|
||||
LDA #$FF ;Pretend that the last data sector used had
|
||||
STX RELPREV ;a relative sector number (in relation to
|
||||
(ABCF) STA RELPREV+1 ;the entire file) of #$FFFF. NOTE: This
|
||||
;value is later used to trick the read and
|
||||
;write subfunctions into ignoring the data
|
||||
;sector currently in memory.
|
||||
(ABD2) LDA MXIN1TSL ;Dictate that a T/S list can only describe $7A
|
||||
(ABD5) STA MXSCURTS ;(#122) data sectors. Note: This value is later
|
||||
;used by the read and write subfunctions to decide
|
||||
;whether or not the T/S list currently in memory
|
||||
;should be used.
|
||||
|
||||
* Read first T/S list sector
|
||||
* to the T/S list buffer.
|
||||
(ABD8) CLC ;(c) = 0 = signal 1rst T/S list sector.
|
||||
(ABD9) JMP READTS ;Go read in the T/S list sector.
|
||||
------------
|
||||
|
||||
* Read T/S list sector.
|
||||
(AF5E)
|
||||
READTS PHP ;Save (c) denoting if 1rst T/S list or not.
|
||||
;(c) = 0 = read 1rst T/S list sec.
|
||||
;(c) = 1 = read next T/S list sec.
|
||||
(AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is
|
||||
;required. (If T/S list buf has changed
|
||||
;since last read or write, then write it
|
||||
;back to the disk so don't overwrite buf
|
||||
;and lose information when read the new
|
||||
;T/S list sector.)
|
||||
|
||||
* Check if T/S list requires updating.
|
||||
* (ie. Has T/S list buf changed since
|
||||
* the last read or write?)
|
||||
(AF34)
|
||||
CKTSUPDT LDA UPDATFLG
|
||||
BMI WRITETS ;If bit 7 set, updating is required.
|
||||
(AF39) RTS ;BRANCH NOT APPLICABLE TO THE LOCK/UNLOCK FUNCTIONS.
|
||||
|
||||
|
||||
(AF62) JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list.
|
||||
|
||||
* Prepare RWTS's IOB for reading
|
||||
* or writing the T/S list sector.
|
||||
(AF4B)
|
||||
SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM
|
||||
STA IBBUFP ;parameter list & designate T/S list buf
|
||||
LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
|
||||
LDY CURTSSEC
|
||||
(AF5D) RTS
|
||||
|
||||
(AF65) JSR SELTSBUF ;Select the T/S list buffer.
|
||||
|
||||
* Point A4L/H at the T/S list sector buffer.
|
||||
(AF0C)
|
||||
SELTSBUF LDX #2 ;Index for T/S list buf.
|
||||
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from
|
||||
STA A4L ;the FM parameter list & put it in the
|
||||
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AF68) PLP ;Get saved (c) back from stack.
|
||||
(AF69) BCS RDNXTTS ;If (c) = 1, already read first T/S list
|
||||
;sec, so go read next one.
|
||||
;ALWAYS FALL THRU WITH LOCK/UNLOCK FUNCTIONS (cause (c)=0).
|
||||
|
||||
* Read first T/S list sector.
|
||||
* (Carry was clear.)
|
||||
(AF6B)
|
||||
RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec.
|
||||
LDY FIRTSSEC
|
||||
(AF71) JMP RDTSLST ;Go read T/S list sector into buffer.
|
||||
------------
|
||||
|
||||
* Subroutine to read/write T/S list sector.
|
||||
(AFB5)
|
||||
RDTSLST LDA #1 ;Read opcode for RWTS.
|
||||
|
||||
* Code common to read/write T/S list.
|
||||
(AFB7)
|
||||
RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y)
|
||||
STY CURTSSEC ;become current T/S list trk/sec values.
|
||||
(AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S
|
||||
;list.
|
||||
|
||||
* Read or write the current T/S list.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Update the FM work area
|
||||
* (not in DOS buffer chain).
|
||||
(AFC0) LDY #5 ;Offset into current T/S list buffer.
|
||||
LDA (A4L),Y ;Get & save the relative sector number of
|
||||
(AFC4) STA RELFIRST ;the first data sector described in this
|
||||
;T/S list.
|
||||
(AFC7) CLC ;Add the maximum # of data secs that
|
||||
ADC MXSCURTS ;can be described in this T/S list ($7A, #122).
|
||||
STA RELASTP1 ;Store relative sector number (plus 1) of
|
||||
INY ;the last data sector described in list.
|
||||
LDA (A4L),Y
|
||||
STA RELFIRST+1
|
||||
ADC MXSCURTS+1
|
||||
STA RELASTP1+1 ;(RELASTP1/+1 is always set to $007A by FNOPEN.)
|
||||
CLC ;Return with "no error" signal.
|
||||
(AFDB) RTS
|
||||
============
|
||||
|
||||
(ACFE) LDX CURDIRNX ;(x) = index to file description entry
|
||||
;in the directory sector buffer.
|
||||
(AD01) LDA FIL1TYPE,X ;Get old file type.
|
||||
AND #$7F ;Shut hi bit off.
|
||||
(AD06) ORA LOKUNMSK ;Merge with LOKUNMSK to set (lock) or clear
|
||||
;(unlock) the hi bit.
|
||||
(AD09) STA FIL1TYPE,X ;Stick modified file type back into the
|
||||
;file description part of the directory
|
||||
;sector buffer.
|
||||
(AD0C) JSR WRDIRECT ;Write the updated directory sec buf to disk.
|
||||
|
||||
* Write the directory buffer.
|
||||
(B037)
|
||||
WRDIRECT JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as the I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sec buf
|
||||
STA IBBUFP ;in the FM constants table.
|
||||
LDA ADRDIRBF+1 ;Store it in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
(B051) RTS
|
||||
|
||||
(B03A) LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec vals.
|
||||
LDY CURDIRSC
|
||||
LDA #2 ;Write opcode for RWTS.
|
||||
(B042) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer.
|
||||
------------
|
||||
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AD0F)
|
||||
TOOKFMXT JMP GOODFMXT ;Exit the file manager cleanly.
|
||||
------------
|
||||
|
||||
|
||||
* Exit the file manager with or without errors.
|
||||
(B35F)
|
||||
LNGNOTAV LDA #1
|
||||
(B361) BNE BADFMXIT ;ALWAYS.
|
||||
|
||||
(B373)
|
||||
FILENOT LDA #6
|
||||
(B375) BNE BADFMXIT ;ALWAYS.
|
||||
|
||||
(B377)
|
||||
DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.)
|
||||
|
||||
(B37F)
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
||||
|
||||
* Copy the FM work area (non-chain) to
|
||||
* the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list & put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;from the stack.
|
||||
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
||||
TXS ;caller of the function handler even if we
|
||||
(B396) RTS ;are several subroutines deeper than the
|
||||
============ ;original entry point. (That is, return
|
||||
;to AFTRFUNC ($A6AB) in the FMDRIVER routine
|
||||
;($A6A8).)
|
454
textfiles.com/apple/ANATOMY/fncatlog.txt
Normal file
454
textfiles.com/apple/ANATOMY/fncatlog.txt
Normal file
@@ -0,0 +1,454 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* CATALOG Function Handler *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* This function handler is only called by the CATALOG *
|
||||
* command. The overall execution pattern of the function, as *
|
||||
* well as several customizing techniques, are described in the *
|
||||
* preamble given with the catalog command handler (CMDCATLG, *
|
||||
* $A56E). *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
(AD98)
|
||||
FNCATLOG JSR ZWRKAREA ;Initialize the work area.
|
||||
|
||||
* Zero out the FM work area so it can be customized
|
||||
* in accordance with the calling function.
|
||||
* (Although some work bytes may not be subsequently
|
||||
* altered, don't be lulled into thinking that they
|
||||
* are not important. Zero values are just as relevant
|
||||
* as non-zero values.)
|
||||
* (P.S. Don't confuse the FM work area with its image
|
||||
* (FM work buffer) that is housed in the chain of
|
||||
* DOS buffers.)
|
||||
(ABDC)
|
||||
ZWRKAREA LDA #0
|
||||
TAX ;Initialize the x-index.
|
||||
ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
|
||||
INX
|
||||
CPX #45 ;Work area is 45 bytes long.
|
||||
(ABE5) BNE ZEROWRKA
|
||||
|
||||
* Begin customizing the work area.
|
||||
* Get volume, drive, slot & catalog track
|
||||
* values from the FM parameter list. Put
|
||||
* drive, slot*16, catalog track and
|
||||
* complemented volume number in the work area.
|
||||
(ABE7) LDA VOLFM ;Volume number.
|
||||
EOR #$FF ;Calculate 1's compliment of volume #.
|
||||
STA VOLWA
|
||||
LDA DRVFM ;Drive #.
|
||||
STA DRVWA
|
||||
LDA SLOTFM ;Get slot #.
|
||||
ASL ;Calculate slot * 16.
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
TAX ;Set (x) = slot * 16.
|
||||
STX SLOT16WA
|
||||
LDA #$11 ;Normal catalog trk = #17.
|
||||
STA TRKWA
|
||||
(AC05) RTS
|
||||
|
||||
(AD9B) LDA #$FF ;Allow any volume to be cataloged.
|
||||
(AD9D) STA VOLWA ;(When RWTS is later entered, this value is
|
||||
;EORed with #$FF to simulate a complemented
|
||||
;volume number of 0 (ie. #$FF EOR #$FF = $00).
|
||||
;After RWTS reads the addr checksum, it chks
|
||||
;to see if the correct volume was read off
|
||||
;the disk. If the complement of the vol #
|
||||
;is 0, or if it matches the vol # read off
|
||||
;the disk, execution proceeds as if the
|
||||
;correct volume was found.)
|
||||
(ADA0) JSR READVTOC ;Read the VTOC.
|
||||
|
||||
* Read the Volume Table of Contents (VTOC).
|
||||
(AFF7)
|
||||
READVTOC LDA #1 ;Read opcode for RWTS.
|
||||
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
||||
|
||||
* Common to read/write the VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get the address of the VTOC from the FM
|
||||
STY IBBUFP ;constants table & designate it as the
|
||||
LDY ADRVTOC+1 ;I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) = trk/sec
|
||||
LDY #0 ;values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call RWTS driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(ADA3) LDA #22 ;Set index to allow 22 screen lines
|
||||
(ADA5) STA SCRNSRCH ;between pauses.
|
||||
|
||||
* Print two <cr>'s & the words
|
||||
* "disk volume".
|
||||
(ADA8) JSR CRCATLOG
|
||||
|
||||
* Print a <cr> and check if a pause is required.
|
||||
(AE2F)
|
||||
CRCATLOG LDA #$8D ;Print a <cr>.
|
||||
JSR COUT
|
||||
(AE34) DEC SCRNSRCH ;Reduce line counter to see if a pause
|
||||
;is required or not.
|
||||
(AE37) BNE CRCATRTN ;No pause required.
|
||||
(AE39) JSR RDKEY ;Pause until a key is pressed, so information
|
||||
;can be absorbed before it scrolled off the
|
||||
;screen.
|
||||
(AE3C) LDA #21 ;Reset the screen line counter.
|
||||
STA SCRNSRCH
|
||||
CRCATRTN RTS
|
||||
(AE41)
|
||||
|
||||
(ADAB) JSR CRCATLOG ;Do it again. (See dis'mbly above.)
|
||||
(ADAE) LDX #11 ;12 chars to print (11 to 0).
|
||||
PRDSKVOL LDA DSKVOLUM,X ;Get char of reverse string.
|
||||
JSR COUT ;Print char.
|
||||
DEX
|
||||
BPL PRDSKVOL ;More chars in string.
|
||||
(ADB9) STX A5L+1 ;Nonsense instruction (cause the hi byte is
|
||||
;not used in the PRVOLNMB routine accessed
|
||||
;below).
|
||||
(ADBB) LDA IBSMOD ;Get vol # found (from RWTS's IOB) and put
|
||||
STA A5L ;it in A5L.
|
||||
(ADC0) JSR PRVOLNMB ;Go print the volume number.
|
||||
|
||||
* Convert 1 hex byte to a three-digit decimal
|
||||
* number (with leading zeroes if applicable).
|
||||
* NOTE: This is a BUGGY routine. Because it
|
||||
* doesn't use the hi byte, numbers greater than
|
||||
* 255 are expressed as 256 mod.
|
||||
* (P.S. To use this as a stand-alone routine,
|
||||
* load A5L with the hex value to be converted
|
||||
* and then call PRVOLNMB. The (a) and (y)
|
||||
* registers are destroyed. Conversion is done
|
||||
* by simulating division via successive subtractions
|
||||
* of powers of 10.)
|
||||
(AE42)
|
||||
PRVOLNMB LDY #2 ;Index for number of conversion factors
|
||||
(AE44) ;and digits.
|
||||
ZONSTK LDA #0 ;Initialize the count of the number of
|
||||
;subtractions done.
|
||||
(AE46) PHA ;Save the count on the stack.
|
||||
GETVNMB LDA A5L ;Get the low byte hex value and compare it
|
||||
(AE49) CMP BASETEN,Y ;to the table of conversion factors.
|
||||
;Conversion table contains powers of 10:
|
||||
; 10^2=100, 10^1=10, 10^0=1.
|
||||
(AE4C) BCC TONEGASC ;Branch if number < conversion factor.
|
||||
SBC BASETEN,Y ;Subtract the conversion factor.
|
||||
STA A5L ;Store the remainder.
|
||||
LDA A5L+1 ;Nonsense - not used.
|
||||
SBC #0 ;Nonsense - not used.
|
||||
STA A5L+1 ;Nonsense - not used.
|
||||
PLA ;Get counter for the number of subtractions.
|
||||
ADC #0 ;Add (c). If remainder > conversion factor,
|
||||
PHA ;then add 1. Else, add nothing.
|
||||
(AE5D) JMP GETVNMB ;Go back to do more subtractions with the
|
||||
------------ ;same conversion factor.
|
||||
TONEGASC PLA ;Get the result of the division (ie. the
|
||||
(AE60) ;whole number of subtractions).
|
||||
(AE61) ORA #$B0 ;Convert count to a negative ASCII char.
|
||||
JSR COUT ;Print the character.
|
||||
DEY ;3 chars/volume number (ie. 2 to 0).
|
||||
BPL ZONSTK ;(3 conversion factors.)
|
||||
(AE69) RTS
|
||||
|
||||
(ADC3) JSR CRCATLOG
|
||||
|
||||
* Print a <cr> and test if a pause is required.
|
||||
(AE2F)
|
||||
CRCATLOG LDA #$8D ;Print a <cr>.
|
||||
JSR COUT
|
||||
(AE34) DEC SCRNSRCH ;Reduce line counter to see if a pause
|
||||
;is required or not.
|
||||
(AE37) BNE CRCATRTN ;No pause required.
|
||||
(AE39) JSR RDKEY ;Pause until a key is pressed, so information
|
||||
;can be absorbed before it scrolled off the
|
||||
;screen.
|
||||
(AE3C) LDA #21 ;Reset the screen line counter.
|
||||
STA SCRNSRCH
|
||||
CRCATRTN RTS
|
||||
(AE41)
|
||||
|
||||
(ADC6) JSR CRCATLOG ;Do it again.
|
||||
|
||||
* Read the directory sector into the
|
||||
* directory sector buffer.
|
||||
(ADC9) CLC ;(c) = 0, read the first directory sector.
|
||||
(ADCA) ;(c) = 1, read the next directory sector.
|
||||
RDDIRSEC JSR RDDIRECT ;Go read the directory sector.
|
||||
|
||||
* Read a directory sector.
|
||||
(B011)
|
||||
RDDIRECT PHP ;Save (c) on the stack:
|
||||
; (c)=0=read the first directory sector.
|
||||
; (c)=1=read the next directory sector.
|
||||
(B012) JSR PT2DIRBF ;Select the directory sector buffer.
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as the I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sector buffer
|
||||
STA IBBUFP ;from the FM constants table & designate it
|
||||
LDA ADRDIRBF+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
(B051) RTS
|
||||
|
||||
(B015) PLP ;Get signal back from stack to see if
|
||||
;dealing with first directory sec or not.
|
||||
(B016) BCS RDNXTDIR ;Go read the next directory sector.
|
||||
|
||||
* Read the first directory sector (c = 0).
|
||||
(B018)
|
||||
RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec values of the first
|
||||
LDX FIRDIRTK ;directory sector (from the the VTOC buf).
|
||||
(B01E) BNE DODIRRD ;ALWAYS - go read in the directory sector.
|
||||
|
||||
* Read the next directory sector (c = 1).
|
||||
(B020)
|
||||
RDNXTDIR LDX DIRLNKTK ;Get the track number of the next directory
|
||||
;sector from the link in the current
|
||||
;directory sector.
|
||||
(B023) BNE GETDIRLK ;Link not zeroed out.
|
||||
SEC ;Link zeroed out, so exit with (c) = 1 to
|
||||
(B026) RTS ;signal that there are no more directory
|
||||
============ ;sectors.
|
||||
|
||||
(B027)
|
||||
GETDIRLK LDY DIRLNKSC ;Get the sector number of the next directory
|
||||
;sector from the link in the current
|
||||
;directory sector.
|
||||
|
||||
* Call to read in the directory sector.
|
||||
(B02A)
|
||||
DODIRRD STX CURDIRTK ;Save the trk/sec values of the directory
|
||||
(B02D) STY CURDIRSC ;sector that we are about to read (so that
|
||||
;they will become the current directory
|
||||
;sector values the next time around).
|
||||
(B030) LDA #1 ;Read opcode for RWTS.
|
||||
(B032) JSR RWTSDRVR ;Call RWTS driver to do the READ.
|
||||
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B035) CLC ;Because link didn't zero out, signal that
|
||||
(B036) RTS ;more directory sectors exist and then exit.
|
||||
============
|
||||
|
||||
(ADCD) BCS TOFMXTOK ;Ran out of directory sectors so go exit.
|
||||
(ADCF) LDX #0 ;Initialize index into the directory sec.
|
||||
|
||||
* Evaluate the track number.
|
||||
(ADD1)
|
||||
DESCRPTK STX CURDIRNX ;Save index to entries into the directory.
|
||||
(ADD4) LDA FIL1TSTK,X ;Trk # of 1rst T/S list for file (from
|
||||
;the file description in directory sec.)
|
||||
(ADD7) BEQ TOFMXTOK ;Trk # = 0, so no more entries in the
|
||||
;current directory buffer.
|
||||
(ADD9) BMI NXDESCRP ;Trk# = $FF = deleted file, so skip it.
|
||||
|
||||
* Check the file status & then print
|
||||
* a locked symbol ("*") or space.
|
||||
(ADDB) LDY #" " ;Default (y) = space in case file not locked.
|
||||
LDA FIL1TYPE,X ;Get the file type.
|
||||
BPL PRLOCODE ;Hi bit is clear so file is unlocked.
|
||||
(ADE2) LDY #"*" ;Reset (y) = locked symbol.
|
||||
PRLOCODE TYA ;Either print an "*" or a space.
|
||||
(ADE5) JSR COUT ;Go print char.
|
||||
|
||||
* Print the character code for the
|
||||
* file type and a trailing space.
|
||||
(ADE8) LDA FIL1TYPE,X ;Get the file type again & make
|
||||
(ADEB) AND #$7F ;sure that the hi bit is off so we can
|
||||
;index the table that contains character
|
||||
;code symbols for the different file types.
|
||||
(ADED) LDY #7 ;Set (y) to indicate that 7 relevant bits
|
||||
;are left after the hi bit is shifted out.
|
||||
(ADEE) ASL ;Throw away the hi bit.
|
||||
CHRTYPIX ASL ;Shift remaining bits until a hi bit is set.
|
||||
(ADF1) BCS PRTFTYPE ;The number of shifts required to set the
|
||||
;carry designates the index to the table
|
||||
;of characters representing the file types.
|
||||
(ADF3) DEY ;Reduce counter for number of shifts done.
|
||||
(ADF4) BNE CHRTYPIX ;No set bits encountered yet, so go back
|
||||
(ADF6) ;to do more shifts.
|
||||
PRTFTYPE LDA FTYPETBL,Y ;Got a set bit, so now get char from the
|
||||
;table of file type symbols.
|
||||
(ADF9) JSR COUT ;Print the file type symbol.
|
||||
(ADFC) LDA #" " ;Print the trailing space.
|
||||
|
||||
* Print the file size (which is
|
||||
* expressed in terms of sectors).
|
||||
(AE01) LDA FIL1SIZE,X ;Get the low & hi bytes of the file size
|
||||
STA A5L ;(in sectors) from the file description in
|
||||
LDA FIL1SIZE+1,X ;the current directory sector & stick
|
||||
STA A5L+1 ;them in A5L/H.
|
||||
(AE0B) JSR PRVOLNMB ;Print the file size.
|
||||
|
||||
* Convert 1 hex byte to a three-digit decimal
|
||||
* number (with leading zeroes if applicable).
|
||||
* NOTE: This is a BUGGY routine. Because it
|
||||
* doesn't use the hi byte, numbers greater than
|
||||
* 255 are expressed as 256 mod.
|
||||
* (P.S. To use this as a stand-alone routine,
|
||||
* load A5L with the hex value to be converted
|
||||
* and then call PRVOLNMB. The (a) and (y)
|
||||
* registers are destroyed. Conversion is done
|
||||
* by simulating division via successive subtractions
|
||||
* of powers of 10.)
|
||||
(AE42)
|
||||
PRVOLNMB LDY #2 ;Index for number of conversion factors and
|
||||
(AE44) ;digits.
|
||||
ZONSTK LDA #0 ;Initialize the count of the number of
|
||||
;subtractions done.
|
||||
(AE46) PHA ;Save the count on the stack.
|
||||
GETVNMB LDA A5L ;Get the low byte hex value and compare it
|
||||
(AE49) CMP BASETEN,Y ;to the table of conversion factors.
|
||||
;Conversion table contains powers of 10:
|
||||
; 10^2=100, 10^1=10, 10^0=1.
|
||||
(AE4C) BCC TONEGASC ;Branch if number < conversion factor.
|
||||
SBC BASETEN,Y ;Subtract the conversion factor.
|
||||
STA A5L ;Store the remainder.
|
||||
LDA A5L+1 ;Nonsense - not used.
|
||||
SBC #0 ;Nonsense - not used.
|
||||
STA A5L+1 ;Nonsense - not used.
|
||||
PLA ;Get counter for the number of subtractions.
|
||||
ADC #0 ;Add (c). If remainder > conversion factor,
|
||||
PHA ;then add 1. Else, add nothing.
|
||||
(AE5D) JMP GETVNMB ;Go back to do more subtractions with the
|
||||
------------ ;same conversion factor.
|
||||
(AE60)
|
||||
TONEGASC PLA ;Get the result of the division (ie. the
|
||||
;whole number of subtractions).
|
||||
(AE61) ORA #$B0 ;Convert count to a negative ASCII char.
|
||||
JSR COUT ;Print the character.
|
||||
DEY ;3 chars/volume number (ie. 2 to 0).
|
||||
BPL ZONSTK ;(3 conversion factors.)
|
||||
(AE69) RTS
|
||||
|
||||
(AE0E) LDA #" " ;Print a space after the size.
|
||||
(AE10) JSR COUT
|
||||
|
||||
* Print the file name.
|
||||
(AE13) INX ;Kick (x) up because the name starts at the
|
||||
INX ;4th byte from the start of the file
|
||||
INX ;description entry.
|
||||
LDY #29 ;Counter for 30 characters/name (0 - 29).
|
||||
PRTFNAME LDA FIL1TSTRK,X ;Get char for file name and print it.
|
||||
(AE1B) JSR COUT ;(P.S. Since the output hook still points
|
||||
;to DOS's output handler, ctrl-D and a
|
||||
;subsequent DOS command can be embedded in
|
||||
;the filename as a protection scheme.)
|
||||
(AE1E) INX ;Kick up index into the file description.
|
||||
DEY ;Reduce the character counter.
|
||||
BPL PRTFNAME ;Branch if more characters to print.
|
||||
(AE22) JSR CRCATLOG ;Print a <cr> after the name & chk 4 pause.
|
||||
|
||||
* Print a <cr> and test if a pause is required.
|
||||
(AE2F)
|
||||
CRCATLOG LDA #$8D ;Print a <cr>.
|
||||
JSR COUT
|
||||
(AE34) DEC SCRNSRCH ;Reduce line counter to see if a pause
|
||||
;is required or not.
|
||||
(AE37) BNE CRCATRTN ;No pause required.
|
||||
(AE39) JSR RDKEY ;Pause until a key is pressed, so information
|
||||
;can be absorbed before it scrolled off the
|
||||
;screen.
|
||||
(AE3C) LDA #21 ;Reset the screen line counter.
|
||||
STA SCRNSRCH
|
||||
CRCATRTN RTS
|
||||
(AE41)
|
||||
|
||||
* Kick up the index into the current
|
||||
* directory sector buffer to point at
|
||||
* the start of the next file description entry.
|
||||
(AE25)
|
||||
NXDESCRP JSR NXPLUS35
|
||||
|
||||
* Add 35 bytes to the index so it points to
|
||||
* the next entry in the current directory
|
||||
* sector.
|
||||
(B230)
|
||||
NXPLUS35 CLC
|
||||
LDA CURDIRNX
|
||||
ADC #35
|
||||
TAX ;Check if there is space left for more
|
||||
CPX #245 ;entries in the current directory sector.
|
||||
(B239) RTS ;Exit with (c) conditioned:
|
||||
; (c) = 0 = more space in directory
|
||||
; sector.
|
||||
; (c) = 1 = no more space, ran off the end
|
||||
; of the directory sector.
|
||||
|
||||
(AE28) BCC DESCRPTK ;(c)=0, so go look for more entries in this
|
||||
;particular directory sector.
|
||||
(AE2A) BCS RDDIRSEC ;(c)=1, so there are no more entries in this
|
||||
------------ ;directory sector. There4, go back to read
|
||||
;in another directory sector.
|
||||
(AE2C)
|
||||
TOFMXTOK JMP GOODFMXT ;Go exit the file manager cleanly.
|
||||
------------
|
||||
|
||||
|
||||
* Exit the file manager.
|
||||
(B37F)
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
||||
|
||||
* Copy the FM work area (non-chain) to
|
||||
* the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list & put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;from the stack.
|
||||
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
||||
TXS ;caller of the function handler even if we
|
||||
(B396) RTS ;are several subroutines deeper than the
|
||||
============ ;original entry point. (That is, return to
|
||||
;AFTRFUNC ($A6AB) in the FMDRIVER routine
|
||||
;($A6A8).)
|
507
textfiles.com/apple/ANATOMY/fnclose.txt
Normal file
507
textfiles.com/apple/ANATOMY/fnclose.txt
Normal file
@@ -0,0 +1,507 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* CLOSE function handler *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* In order to understand the execution pattern of the close *
|
||||
* function handler (FNCLOSE, $AC06) you must first be familiar *
|
||||
* with the writing process. As a file is being written, data *
|
||||
* are transferred from their source memory locations to the DOS *
|
||||
* data sector buffer. Each time the data sector buffer is *
|
||||
* filled, it is automatically written to the disk. However, if *
|
||||
* the last segment of data does not completely fill the buffer, *
|
||||
* the write process is exited with bit six of the update flag *
|
||||
* (UPDATFLG, $B5D5) set. When the file is subsequently closed, *
|
||||
* FNCLOSE tests UPDATFLG and writes the data sector buffer if *
|
||||
* necessary. A similar situation occurs with the T/S list *
|
||||
* buffer. FNCLOSE also tests bit seven of UPDATFLG to see if *
|
||||
* the T/S list requires updating. If the T/S list buffer has *
|
||||
* changed since the last read or write, it is written to the *
|
||||
* disk. *
|
||||
* After updating the data and T/S list buffers on the disk *
|
||||
* (if necessary), FNCLOSE calls the FIXMAP routine ($B2C3) to *
|
||||
* free up any sectors that were assigned in the VTOC but not *
|
||||
* used. (This step is necessary because the write process *
|
||||
* allocates an entire track to the file even if only a few *
|
||||
* sectors are required.) *
|
||||
* Once the VTOC is updated on the disk, the new file-size *
|
||||
* bytes are stored in the appropriate file description entry of *
|
||||
* the directory buffer. Finally the directory buffer is written *
|
||||
* to the disk and the close function handler is exited. *
|
||||
* *
|
||||
* As described above, the FIXMAP routine ($B2C3) frees up *
|
||||
* any sectors that were unnecessarily assigned to a file. *
|
||||
* Therefore, if you happen to hit the reset key or turn the *
|
||||
* computer off before a file is closed, the disk may be left *
|
||||
* with several allocated but unused sectors. This wasted disk *
|
||||
* space can only be recovered with a disk repair program or by *
|
||||
* manually updating the VTOC as follows: *
|
||||
* - Catalog the disk. *
|
||||
* - Enter the monitor (type: CALL -151 <rtn>). *
|
||||
* - Correct offending TRKMAP bytes (see description *
|
||||
* of the VTOC given in the linear disassembly). *
|
||||
* - Update the VTOC on the disk (type: AFFBG <rtn>). *
|
||||
* A file must be at least two sectors long (one T/S list *
|
||||
* sector and one data sector) to be useful. Therefore, if you *
|
||||
* encounter a catalog which describes a one-sector long file, *
|
||||
* you can be sure that (a) the file-size bytes in the file's *
|
||||
* description entry were zapped, (b) the file is 257 sectors *
|
||||
* long (001 in 256 modulus format) or (c) a new file was opened *
|
||||
* but never closed. *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
(AC06)
|
||||
FNCLOSE JSR CKDATUP ;Write data sector buffer if necessary.
|
||||
|
||||
* Check if the data sector buffer has
|
||||
* changed since the last read or write.
|
||||
(AF1D)
|
||||
CKDATUP BIT UPDATFLG ;Check bit 6 to see if changed.
|
||||
BVS WRITDATA ;Take branch if changed.
|
||||
(AF22) RTS
|
||||
============
|
||||
|
||||
* Write the present data sector buffer to the disk.
|
||||
* (Updates the disk so that we can read in the next
|
||||
* data sector without overwriting, and therefore losing,
|
||||
* previous data.)
|
||||
(AF23)
|
||||
WRITDATA JSR PRPDAIOB ;Prepare to write the data sector buffer.
|
||||
|
||||
* Prepare RWTS's IOB to read/write
|
||||
* the data sector buffer.
|
||||
(AFE4)
|
||||
PRPDAIOB LDY DATBUFFM ;Get address of the data sector buffer
|
||||
LDA DATBUFFM+1 ;from the FM parameter list and designate
|
||||
STY IBBUFP ;it as the I/O buffer for RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
LDX CURDATRK ;Enter RWTS driver with (x)/(y) = trk/sec
|
||||
LDY CURDATSC ;values for the data sector.
|
||||
(AFF6) RTS
|
||||
|
||||
(AF26) LDA #2 ;Write opcode for RWTS.
|
||||
(AF28) JSR RWTSDRVR ;Call RWTS driver to write the data sector buffer.
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AF2B) LDA #%10111111 ;Shut bit 6 off in the update flag to
|
||||
AND UPDATFLG ;signal that the data sector buffer is
|
||||
STA UPDATFLG ;now up to date.
|
||||
(AF33) RTS
|
||||
============
|
||||
|
||||
(AC09) JSR CKTSUPDT ;Write T/S list sec buf if updating is
|
||||
;required. (If T/S list buf has changed
|
||||
;since last read or write, then write it
|
||||
;back to the disk so don't overwrite buf
|
||||
;and lose information when read the new
|
||||
;T/S list sector.)
|
||||
|
||||
* Check if T/S list requires updating.
|
||||
* (ie. Has T/S list buf changed since
|
||||
* the last read or write?)
|
||||
(AF34)
|
||||
CKTSUPDT LDA UPDATFLG
|
||||
BMI WRITETS ;If bit 7 set, updating is required.
|
||||
(AF39) RTS
|
||||
============
|
||||
|
||||
* Write the updated T/S list sector buffer.
|
||||
(AF3A)
|
||||
WRITETS JSR SETTSIOB ;Prepare to write the T/S list.
|
||||
|
||||
* Prepare RWTS's IOB for reading
|
||||
* or writing the T/S list sector.
|
||||
(AF4B)
|
||||
SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM
|
||||
STA IBBUFP ;parameter list & designate T/S list buf
|
||||
LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
|
||||
LDY CURTSSEC
|
||||
(AF5D) RTS
|
||||
|
||||
(AF3D) LDA #2 ;Write opcode for RWTS.
|
||||
(AF3F) JSR RWTSDRVR ;Call RWTS driver to write the T/S list sector.
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AF42) LDA #$7F ;Clear bit 7 of the update flag to
|
||||
AND UPDATFLG ;signal that the T/S list sec is up to date.
|
||||
STA UPDATFLG
|
||||
(AF4A) RTS
|
||||
============
|
||||
|
||||
(AC0C) JSR FIXMAP
|
||||
|
||||
* Free up sectors that were assigned but
|
||||
* not used. Whenever something is written
|
||||
* to the disk, the whole trk is allocated in
|
||||
* the VTOC whether it is needed or not.
|
||||
* There4, once we are done writing, go back
|
||||
* and free up the unneeded sectors.
|
||||
(B2C3)
|
||||
FIXMAP LDA SIGNTRK ;Has a track already been assigned?
|
||||
BNE FREEXTRA ;Yes - go free up the extra sectors.
|
||||
(B2C8) RTS ;No - go exit.
|
||||
============
|
||||
|
||||
(B2C9)
|
||||
FREEXTRA PHA ;Save trk number on the stack.
|
||||
(B2CA) JSR READVTOC ;Read in the VTOC.
|
||||
|
||||
* Read the Volume Table of Contents (VTOC).
|
||||
(AFF7)
|
||||
READVTOC LDA #1 ;Read opcode for RWTS.
|
||||
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
||||
|
||||
* Code common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
||||
STY IBBUFP ;FM constants table & designate it
|
||||
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
||||
LDY #0 ;to the trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call RWTS driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dism'bly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B2CD) LDY ASIGNSEC ;Number of next sec which could
|
||||
;have been written.
|
||||
(B2D0) PLA ;Get assignment track # back from the stack.
|
||||
(B2D1) CLC ;We don't want to free the last sector used,
|
||||
;so clear the carry here so we don't free
|
||||
;that sector up when we begin rotating the
|
||||
;usage maps in the SUB2FREE routine below.
|
||||
(B2D2) JSR SUB2FREE ;Adjust assignment map to free up sectors
|
||||
;by setting bit corresponding to the sector
|
||||
;number. Next, merge ASIGNMAP with the
|
||||
;appropriate trk map in the VTOC.
|
||||
|
||||
* Subroutine to free up sectors that were
|
||||
* deleted or prematurely assigned but not used.
|
||||
*
|
||||
* This tricky little routine is easy to
|
||||
* understand once you realize that:
|
||||
* 1) Unlike the VTOC, ASIGNMAP does not
|
||||
* contain any unnecessarily assigned
|
||||
* sectors.
|
||||
* 2) If the disk was just written to,
|
||||
* ASIGNMAP does not house any newly
|
||||
* assigned sectors (even if those sectors
|
||||
* are necessary or not).
|
||||
* 3) Sectors are normally assigned in
|
||||
* descending order.
|
||||
* 4) The number of ROR's done = number
|
||||
* of sectors that need to be assigned.
|
||||
* For example: If the last track had never
|
||||
* been assigned and only sectors $0F and
|
||||
* $0E were needed, then on entry to SUB2FREE,
|
||||
* the first two bytes would appear as follows:
|
||||
* Sector numbers: CBA98765 43210FED
|
||||
* Bit values: 11111111 11111...
|
||||
* After the first ROR, the status of sector
|
||||
* $0D is determined by the entry status of
|
||||
* the carry (c):
|
||||
* Sector numbers: DCBA9876 543210FE
|
||||
* Bit values: c1111111 111111..
|
||||
* On the next ROR, the "CPY SECPERTK"
|
||||
* instruction conditions (c) to clear for
|
||||
* sector $0E:
|
||||
* Sector numbers: EDCBA987 6543210F
|
||||
* Bit values: 0c111111 1111111.
|
||||
* On the next ROR, the "CPY SECPERTK"
|
||||
* instruction conditions (c) to clear for
|
||||
* sector $0F:
|
||||
* Sector numbers: FEDCBA98 76543210
|
||||
* Bit values: 00c11111 11111111
|
||||
* When ASIGNMAP is merged with the corresponding
|
||||
* TRKMAP in the VTOC, the sectors that were
|
||||
* unnecessarily assigned in the VTOC are
|
||||
* freed. (Note: When used in the DELETE
|
||||
* function, SUB2FREE is repeatedly called
|
||||
* up by FREESEC to free one sector at a time.)
|
||||
(B2DD)
|
||||
SUB2FREE LDX #$FC ;Set index to shift 4 bytes as a unit
|
||||
(B2DF) ;(#$FC --> #$FF).
|
||||
STNDARD ROR ASIGNMAP-$FC,X ;4 bytes = map for 1 track.
|
||||
INX
|
||||
BNE STNDARD
|
||||
(B2E5) INY ;When (y) = 16, ASIGNMAP is back in
|
||||
;standard position.
|
||||
(B2E6) CPY SECPERTK ;Condition (c) for next shift.
|
||||
BNE SUB2FREE
|
||||
ASL ;Trk*4 to index TRKMAP.
|
||||
ASL
|
||||
TAY
|
||||
(B2EE) BEQ SUB2RTN ;Track value of 0 not allowed.
|
||||
|
||||
* ASIGNMAP now reflects the true sector assignment
|
||||
* and is in standard position. Therefore, merge it
|
||||
* with the appropriate TRKMAP in the VTOC to free up
|
||||
* extra sectors.
|
||||
(B2F0) LDX #4
|
||||
MERGMAPS LDA ASIGNMAP-1,X
|
||||
ORA TRKMAP0+3,Y ;Do the merge.
|
||||
STA TRKMAP0+3,Y
|
||||
DEY ;Reduce indices.
|
||||
DEX
|
||||
BNE MERGMAPS
|
||||
SUB2RTN RTS
|
||||
(B2FF)
|
||||
|
||||
(B2D5) LDA #0 ;No more deallocations needed.
|
||||
STA ASIGNTRK
|
||||
(B2DA) JMP WRITVTOC ;Write the corrected VTOC back to the disk.
|
||||
------------
|
||||
|
||||
* Write the Volume Table of Contents (VTOC).
|
||||
(AFFB)
|
||||
WRITVTOC LDA #2 ;Write opcode for RWTS.
|
||||
|
||||
* Code common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
||||
STY IBBUFP ;FM constants table & designate it
|
||||
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
||||
LDY #0 ;to the trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dism'bly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Was the last last operation a WRITE?
|
||||
(AC0F) LDA #%00000010 ;If bit 1 is set, then just did a write.
|
||||
AND UPDATFLG
|
||||
(AC14) BEQ TOGDFMXT ;Last operation wasn't a write, so we can
|
||||
;just exit because there is no need to
|
||||
;update the directory sector.
|
||||
|
||||
* The last operation was a write, so
|
||||
* we better prepare to fix up the
|
||||
* file-size and T/S link bytes in
|
||||
* the directory sector.
|
||||
(AC16) JSR READVTOC ;Read the VTOC.
|
||||
|
||||
* Read the Volume Table of Contents (VTOC).
|
||||
(AFF7)
|
||||
READVTOC LDA #1 ;Read opcode for RWTS.
|
||||
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
||||
|
||||
* Code common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
||||
STY IBBUFP ;FM constants table & designate it
|
||||
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
||||
LDY #0 ;to the trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dism'bly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Read in all the directory sectors up
|
||||
* to the directory sector containing the
|
||||
* file description entry corresponding to
|
||||
* the file we are closing.
|
||||
(AC19) LDA #0
|
||||
(AC1B) CLC ;(c) = 0 = signal to read the first
|
||||
(AC1C) ;directory sector.
|
||||
PURGEDIR JSR RDDIRECT ;Go read directory sector into buffer.
|
||||
|
||||
* Read a directory sector.
|
||||
(B011)
|
||||
RDDIRECT PHP ;Save (c) on stack:
|
||||
; (c) = 0 = read 1rst directory sector.
|
||||
; (c) = 1 = read next directory sector.
|
||||
(B012) JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get addr of direc
|
||||
STA IBBUFP ;sec buf from the
|
||||
LDA ADRDIRBF+1 ;FM constants tbl
|
||||
STA IBBUFP+1 ;& designate it as
|
||||
(B051) RTS ;as the I/O buffer.
|
||||
|
||||
(B015) PLP ;Check if 1rst directory sec or not.
|
||||
(B016) BCS RDNXTDIR ;Go read next directory sector.
|
||||
|
||||
* Read the first directory sector.
|
||||
* (Carry = 0.)
|
||||
(B018)
|
||||
RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory
|
||||
LDX FIRDIRTK ;sector (from the VTOC buffer).
|
||||
(B01E) BNE DODIRRD ;ALWAYS - go read in directory sector.
|
||||
|
||||
* Read the next directory sector.
|
||||
* (Carry = 1.)
|
||||
(B020)
|
||||
RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
(B023) BNE GETDIRLK ;Link not zeroed out.
|
||||
SEC ;Link zeroed out - exit with (c) = 1 to
|
||||
(B026) RTS ;signal there are no more directory secs.
|
||||
============
|
||||
|
||||
(B027)
|
||||
GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
|
||||
* Call to read in the directory sector.
|
||||
(B02A)
|
||||
DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that
|
||||
(B02D) STY CURDIRSC ;we are about to read so they will be
|
||||
;the current directory sec values for the
|
||||
;next time around.
|
||||
(B030) LDA #1 ;Read opcode for RWTS.
|
||||
(B032) JSR RWTSDRVR ;Call RWTS driver to do the read.
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B035) CLC ;Link didn't zero out so signal that there
|
||||
(B036) RTS ;are more directory secs to read & exit.
|
||||
============
|
||||
|
||||
(AC1F) SEC ;(c) = 1 = already read first directory sec.
|
||||
DEC SECNXD1R ;Index for # of directory sectors.
|
||||
(AC23) BNE PURGEDIR ;If 0, then just read directory sector
|
||||
;corresponding to the file wanted.
|
||||
|
||||
* Update the file size and write
|
||||
* the directory sector to the disk.
|
||||
(AC25) LDX BYTNXD1R ;(x) = offset of the file description in the
|
||||
;directory sector.
|
||||
(AC28) LDA FILENSEC ;Number of secs in file (from FM work area).
|
||||
STA FIL1SIZE,X
|
||||
LDA FILENSEC+1
|
||||
STA FIL1SIZE+1,X
|
||||
(AC34) JSR WRDIRECT ;Write the updated directory sector.
|
||||
|
||||
* Write the directory buffer.
|
||||
(B037)
|
||||
WRDIRECT JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as the I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sec buf
|
||||
STA IBBUFP ;in the FM constants table.
|
||||
LDA ADRDIRBF+1 ;Store it in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
(B051) RTS
|
||||
|
||||
(B03A) LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec vals.
|
||||
LDY CURDIRSC
|
||||
LDA #2 ;Write opcode for RWTS.
|
||||
(B042) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer.
|
||||
------------
|
||||
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AC37)
|
||||
TOGDFMXT JMP GOODFMXT ;Exit file manager cleanly.
|
||||
------------
|
||||
|
||||
|
||||
* Exit the file manager.
|
||||
(B37F)
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
||||
|
||||
* Copy the FM work area (non-chain) to
|
||||
* the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list & put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;from the stack.
|
||||
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
||||
TXS ;caller of the function even if we are
|
||||
(B396) RTS ;several subroutines deeper than the
|
||||
============ ;original entry point. (Returns to AFTRFUNC
|
||||
;($A6AB) in the FMDRIVER routine ($A6A8).)
|
991
textfiles.com/apple/ANATOMY/fndelete.txt
Normal file
991
textfiles.com/apple/ANATOMY/fndelete.txt
Normal file
@@ -0,0 +1,991 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* DELETE Funtion Handler *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* The DELETE function handler (FNDELETE, $AD2B) uses the *
|
||||
* COMNOPEN routine ($AB28) to locate the desired file. COMNOPEN *
|
||||
* configures the FM work area, reads in a fresh VTOC and then *
|
||||
* searches the directory sectors for the file description entry *
|
||||
* of the wanted file. (The links to the first directory sector *
|
||||
* are housed in the VTOC. Each subsequent directory sector *
|
||||
* contains the links to the next directory sector. The link *
|
||||
* bytes of the last directory sector are zeroed out.) *
|
||||
* Each directory contains up to seven different file *
|
||||
* descriptions. An example of the data contained in a file *
|
||||
* description is shown below: *
|
||||
* FIL1TSTK DS 1 ;Track # of first T/S list for file 1. *
|
||||
* FIL1TSSC DS 1 ;Sector # of first T/S list for file 1. *
|
||||
* FIL1TYPE DS 1 ;File type code for file 1. ($00=Text, *
|
||||
* ;$01=Integer, $02=Applesoft, $04=Binary, *
|
||||
* ;$08=S-type, $10=Relocatable, $20=A-type *
|
||||
* ;and $40=B-type.) The hi bit is set on *
|
||||
* ;locked files. For example, $02=unlocked *
|
||||
* ;Applesoft and $82=locked Applesoft. *
|
||||
* FIL1NAME DS 30 ;Name of file 1. If a file name less than *
|
||||
* ;30 bytes is used, trailing spaces are *
|
||||
* ;added to the name to fill the buffer. *
|
||||
* FIL1SIZE DS 2 ;Size of file 1 in terms of the number of *
|
||||
* ;sectors used. *
|
||||
* (If a file was deleted, the track # of the first T/S list sec *
|
||||
* was copied to the last byte position of the name field. The *
|
||||
* original track # byte (FIL1TSTK) was then overwritten with *
|
||||
* an #$FF.) *
|
||||
* As each directory sector is read in, an attempt is made *
|
||||
* to locate a file description which contains the name of the *
|
||||
* file wanted. If, after searching all directories, the name of *
|
||||
* the wanted file is not found, a second search is made to *
|
||||
* locate the first available space in a directory where a new *
|
||||
* file description can be placed (in case the command can *
|
||||
* legally create a new file). If no free space is located, a *
|
||||
* disk-full error message is printed. *
|
||||
* If a free space is found, NEWDESCRP ($B21C) copies the *
|
||||
* name of the wanted file from the primary file name buffer *
|
||||
* (PRIMFNBF, $AA75) into the new entry space. A check is then *
|
||||
* made to see if the command can legally create a new file. The *
|
||||
* identifying command byte (NDX2CMD, $AA5F) is used to index a *
|
||||
* table of command attributes (CMDATTRB, $A909). Because bit0 *
|
||||
* of the first attribute byte associated with the delete *
|
||||
* command is clear, a new file cannot legally be created. As a *
|
||||
* result, the delete command is exited with a file-not-found *
|
||||
* error message. *
|
||||
* If a (non-deleted) description entry containing the name *
|
||||
* of the wanted file is located, execution branches to the *
|
||||
* FILLINWA routine ($ABA6). FILLINWA uses the information *
|
||||
* contained in the description entry to customize the FM work *
|
||||
* area. The first T/S list belonging to the wanted file is then *
|
||||
* read in (READTS, $A5FE). Next, the file type code is checked. *
|
||||
* The delete command is aborted with a file-locked message if *
|
||||
* the file is locked. *
|
||||
* If the file is not locked, the track value of the file's *
|
||||
* first T/S list is copied to the last character position of the *
|
||||
* name field in the description. The original track number byte *
|
||||
* is then replaced with an #$FF to mark the file as deleted. *
|
||||
* WRDIRECT ($B037) is used to write the updated directory sector *
|
||||
* to the disk. After re-reading the file's first T/S list into *
|
||||
* the T/S list buffer, execution returns to the delete function *
|
||||
* handler at $AD5C. *
|
||||
* The DELFREE routine ($AD5E) is used to free up all the *
|
||||
* data sectors that are listed in the T/S list. Sectors are *
|
||||
* released by setting the appropriate bit in the TRKMAP bytes of *
|
||||
* the VTOC. (See the linear disassembly of the VTOC and the *
|
||||
* SUB2FREE routine ($B2DD) listed below for further explanation.)*
|
||||
* After all data sectors listed in the T/S list are *
|
||||
* freed, the sector belonging to the T/S list is also released *
|
||||
* ($ADD7). Execution then branches back to the RDTS4DEL routine *
|
||||
* ($AD54) to read in the next T/S list and repeat the freeing up *
|
||||
* process (if necessary). Once all the sectors associated with *
|
||||
* the file are released, a forced branch is made to the DONEDEL *
|
||||
* routine ($AD83). DONEDEL writes the updated VTOC and then *
|
||||
* returns to delete command handler. *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
(AD2B)
|
||||
FNDELETE JSR COMNOPEN ;Locate a file with the same name & open it.
|
||||
|
||||
*** NOTE ***
|
||||
* Not all of the common open routine is
|
||||
* listed below because not all of it
|
||||
* applies to the DELETE function.
|
||||
|
||||
* Common open routine.
|
||||
(AB28)
|
||||
COMNOPEN JSR ZWRKAREA ;Initialize the work area.
|
||||
|
||||
* Zero out the FM work area so it can be customized
|
||||
* in accordance with the calling function.
|
||||
* (Although some work bytes may not be subsequently
|
||||
* alterd, don't be lulled into thinking that they
|
||||
* are not important. Zero values are just as relevant
|
||||
* as non-zero values.)
|
||||
* (P.S. Don't confuse the FM work area with its image
|
||||
* (FM work buffer) that is housed in the chain of
|
||||
* DOS buffers.)
|
||||
(ABDC)
|
||||
ZWRKAREA LDA #0
|
||||
TAX ;Initialize the x-index.
|
||||
ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
|
||||
INX
|
||||
CPX #45 ;Work area is 45 bytes long.
|
||||
(ABE5) BNE ZEROWRKA
|
||||
|
||||
* Begin customizing the work area.
|
||||
* Get volume, drive, slot & catalog track
|
||||
* values from the FM parameter list. Put
|
||||
* drive, slot*16, catalog track and
|
||||
* complemented volume number in the work area.
|
||||
(ABE7) LDA VOLFM ;Volume number.
|
||||
EOR #$FF ;Calculate 1's complement of volume #.
|
||||
STA VOLWA
|
||||
LDA DRVFM ;Drive #.
|
||||
STA DRVWA
|
||||
LDA SLOTFM ;Get slot #.
|
||||
ASL ;Calculate slot * 16.
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
TAX ;Set (x) = slot * 16.
|
||||
STX SLOT16WA
|
||||
LDA #$11 ;Normal catalog trk = #17.
|
||||
STA TRKWA
|
||||
(AC05) RTS
|
||||
|
||||
(AB2B) LDA #1 ;Describe sector length as 256 bytes
|
||||
(AB2D) STA SECSIZWA+1 ;(in the FM work area).
|
||||
|
||||
* Get record length from the FM parameter
|
||||
* list & put it in the FM work area.
|
||||
* (Don't allow a zero length. If zero,
|
||||
* change it to one.)
|
||||
(AB30) LDX RECLENFM+1
|
||||
LDA RECLENFM
|
||||
BNE STRECLEN ;Non-zero record length is ok.
|
||||
CPX #0
|
||||
BNE STRECLEN
|
||||
INX ;Was zero, make it one instead.
|
||||
STRECLEN STA RECLENWA ;Put length in FM work area.
|
||||
STX RECLENWA+1
|
||||
(AB43) JSR GETFNTRY ;Try to find a directory sector for the file.
|
||||
|
||||
* Locate or create a file entry in the
|
||||
* directory buffer.
|
||||
* Make two searches if necessary:
|
||||
* - Search1 - try to locate entry with same name as file wanted.
|
||||
* - Search2 - couldn't locate entry corresponding to file
|
||||
* wanted so create a new entry in first available
|
||||
* space in the directory sector.
|
||||
(B1C9)
|
||||
GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to
|
||||
;TRKMAPS & to the first directory sector.
|
||||
|
||||
* Read the Volume Table of Contents (VTOC).
|
||||
(AFF7)
|
||||
READVTOC LDA #1 ;Read opcode for RWTS.
|
||||
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
||||
|
||||
* Code common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
||||
STY IBBUFP ;FM constants table & designate it
|
||||
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
||||
LDY #0 ;to the trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dism'bly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Point A4L/H at the primary file name buffer.
|
||||
(B1CC) LDA FNAMBUFM ;Get address of the name buffer from the
|
||||
STA A4L ;FM parameter list & put it in the A4L/H
|
||||
LDA FNAMBUFM+1 ;pointer.
|
||||
(B1D4) STA A4L+1
|
||||
|
||||
* Try to find the directory sector with the
|
||||
* wanted file name & read it into the directory
|
||||
* sector buffer. Make two searches if necessary.
|
||||
* On the first search, try to find a matching name.
|
||||
* If that doesn't work, do a second search to store
|
||||
* the description in the first available file
|
||||
* description field in a directory sector.
|
||||
(B1D6) LDA #1 ;Initialize the search counter (SCRNSRCH)
|
||||
SETSRCH STA SCRNSRCH ;in the FM scratch space for two searches.
|
||||
(B1D8) ;(1 = search1, 0 = search2)
|
||||
(B1DB) LDA #0 ;Initialize offset of file description from
|
||||
STA SECNXDIR ;the very first directory sector.
|
||||
CLC ;(c)=0=signal to read first directory sec.
|
||||
GETDIRSC INC SECNXDIR ;Kick up offset from first directory.
|
||||
(B1E4) JSR RDDIRECT ;Go read directory sector into buffer.
|
||||
|
||||
* Read a directory sector.
|
||||
(B011)
|
||||
RDDIRECT PHP ;Save (c) on stack:
|
||||
; (c) = 0 = read 1rst directory sector.
|
||||
; (c) = 1 = read next directory sector.
|
||||
(B012) JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get addr of direc
|
||||
STA IBBUFP ;sec buf from the
|
||||
LDA ADRDIRBF+1 ;FM constants tbl
|
||||
STA IBBUFP+1 ;& designate it as
|
||||
(B051) RTS ;as the I/O buffer.
|
||||
|
||||
(B015) PLP ;Check if 1rst directory sec or not.
|
||||
(B016) BCS RDNXTDIR ;Go read next directory sector.
|
||||
|
||||
* Read the first directory sector.
|
||||
* (Carry = 0.)
|
||||
(B018)
|
||||
RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory
|
||||
LDX FIRDIRTK ;sector (from the VTOC buffer).
|
||||
(B01E) BNE DODIRRD ;ALWAYS - go read in directory sector.
|
||||
|
||||
* Read the next directory sector.
|
||||
* (Carry = 1.)
|
||||
(B020)
|
||||
RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
(B023) BNE GETDIRLK ;Link not zeroed out.
|
||||
SEC ;Link zeroed out - exit with (c) = 1 to
|
||||
(B026) RTS ;signal there are no more directory secs.
|
||||
============
|
||||
|
||||
(B027)
|
||||
GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
|
||||
* Call to read in the directory sector.
|
||||
(B02A)
|
||||
DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that
|
||||
(B02D) STY CURDIRSC ;we are about to read so they will be
|
||||
;the current directory sec values for the
|
||||
;next time around.
|
||||
(B030) LDA #1 ;Read opcode for RWTS.
|
||||
(B032) JSR RWTSDRVR ;Call RWTS driver to do the read.
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B035) CLC ;Link didn't zero out so signal that there
|
||||
(B036) RTS ;are more directory secs to read & exit.
|
||||
============
|
||||
|
||||
(B1E7) BCS CHNGSRCH ;Link zeroed out, no more directory secs,
|
||||
;so go switch searches.
|
||||
(B1E9) LDX #0
|
||||
CKDIRTRK STX CURDIRNX ;Offset of file description into the current
|
||||
(B1EB) ;directory sector.
|
||||
(B1EE) LDA FIL1TSTK,X ;Get track number of first T/S list
|
||||
;for a particular file from the file
|
||||
;description entry in the directory sector.
|
||||
(B1F1) BEQ CHRSRCHA ;If trk=0, no more files in this direc sec.
|
||||
(B1F3) BMI CHRSRCHB ;Skip deleted file. (When a file is
|
||||
;deleted, #$FF is put in byte where trk #
|
||||
;of first T/S list is usually kept.
|
||||
|
||||
* Compare the name found in the file
|
||||
* description entry portion of the
|
||||
* directory sector with the file name
|
||||
* wanted. (On entry, A4L/H points at
|
||||
* the primary file name buffer.)
|
||||
(B1F5) LDY #0 ;Initialize index to file name buffer.
|
||||
INX ;Point (x) at the first char position
|
||||
INX ;in the name field of description entry.
|
||||
CMPNAMES INX
|
||||
LDA (A4L),Y ;Get char of name from primary.
|
||||
CMP FIL1TSTRK,X ;Compare to char in name of description.
|
||||
BNE DONTMTCH ;Chars (and therefore names) don't match.
|
||||
INY
|
||||
CPY #30 ;Done all chars yet (0 to 29)?
|
||||
BNE CMPNAMES ;Chars matched, branch if more to check.
|
||||
LDX CURDIRNX ;All chars matched, so names matched.
|
||||
CLC ;Return with (x) = index to file
|
||||
(B20A) RTS ;description in current directory sector
|
||||
============ ;and with (c) = 0 to signal that the
|
||||
;correct file description was found.
|
||||
|
||||
* Advance index to point at the next
|
||||
* potential file description entry.
|
||||
(B20B)
|
||||
DONTMTCH JSR NXPLUS35 ;Names didn't match, so adjust index
|
||||
;to point at the next entry.
|
||||
|
||||
* Add 35 to the offset to point the index
|
||||
* at the next file description entry.
|
||||
* (Check to make sure that we don't index
|
||||
* right off the end of the directory sec.)
|
||||
(B230)
|
||||
NXPLUS35 CLC
|
||||
LDA CURDIRNX
|
||||
(B234) ADC #35 ;Add 35 to index. (Each file description
|
||||
;entry is 35 bytes long.)
|
||||
(B236) TAX ;Check if there is more space for entries
|
||||
CPX #245 ;in the current directory sector.
|
||||
(B239) RTS ;Exit with (c) conditioned:
|
||||
; (c) = 0 = more space in directory.
|
||||
; (c) = 1 = ran off end of directory.
|
||||
|
||||
(B20E) BCC CKDIRTRK ;More potential file descriptions to check
|
||||
;in this directory sector.
|
||||
(B210) BCS GETDIRSC ;Go get next directory sector.
|
||||
------------
|
||||
|
||||
* If we just completed the first search,
|
||||
* go back to do the second search.
|
||||
(B212)
|
||||
CHRSRCHA LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B215) BNE SETSRCH ;Go switch to second search.
|
||||
|
||||
* If first search, skip deleted files.
|
||||
* If second search, fall through to store
|
||||
* the description in the first unused
|
||||
* space in the directory.
|
||||
(B217)
|
||||
CHRSRCHB LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B21A) BNE DONTMTCH
|
||||
|
||||
* Couldn't locate the named file in the
|
||||
* directory description entries, so begin
|
||||
* creating a new description in the first available
|
||||
* space in a directory (in case command can
|
||||
* legally create a new file).
|
||||
(B21C)
|
||||
NWDESCRP LDY #0 ;Initialize index to primary file name buffer.
|
||||
INX ;Set index to first char position in the
|
||||
INX ;name field of the file description entry
|
||||
SETNWNAM INX ;space in the directory sector.
|
||||
LDA (A4L),Y ;Copy char from primary file name buffer
|
||||
STA FIL1TSTK,X ;to the directory description space.
|
||||
INY
|
||||
CPY #30 ;30 chars in name (0 to 29).
|
||||
BNE SETNWNAM ;Branch if more chars to copy.
|
||||
LDX CURDIRNX ;Return with (x) = index to file
|
||||
SEC ;description space in current directory
|
||||
(B22F) RTS ;sector & with (c)=1 to signal new entry
|
||||
============ ;was just created.
|
||||
|
||||
* If first search, switch to second search.
|
||||
* If second search, link zeroed out because
|
||||
* there isn't enough room left on the
|
||||
* disk for a new entry. Therefore,
|
||||
* exit with a disk-full error message.
|
||||
(B23A)
|
||||
CHNGSRCH LDA #0 ;Used to reset search counter if
|
||||
;go back to start second search.
|
||||
(B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B23F) BNE SETSRCH ;Just did first search, so go start
|
||||
;the second search.
|
||||
(B241) JMP DISKFULL ;Even second search was unsuccesful
|
||||
------------ ;so go handle a disk-full error.
|
||||
|
||||
(AB46) BCC FILLINWA ;Branch if found a directory sector with
|
||||
;name wanted in the file description entry.
|
||||
|
||||
* Named file wasn't found in directory,
|
||||
* so prepare a new file entry in case
|
||||
* command can legally create a new file.
|
||||
(AB48) STX CURDIRNX ;Offset to new description entry in
|
||||
;case want to create a new file.
|
||||
|
||||
* Check to see if command can
|
||||
* legally create a new file.
|
||||
(AB4B) LDX NDX2CMD ;(x) = index representing command.
|
||||
(AB4E) LDA CMDATTRB,X ;Get first byte containing description
|
||||
;of the given command's attributes.
|
||||
(AB51) LDX CURDIRNX ;(x) = index for new file description
|
||||
;entry into the directory sector.
|
||||
(AB54) LSR ;(c) = bit 0 of 1rst attribute byte.
|
||||
(AB55) BCS CREATNEW ;If (c) = 1, command can create a new file.
|
||||
;ALWAYS FALL THRU FOR DELETE FUNCTION (cause (c) = 0).
|
||||
|
||||
* Command can't create a new file.
|
||||
* See which language we are using and
|
||||
* exit with the appropriate error msg.
|
||||
(AB57)
|
||||
NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM),
|
||||
;$80=coldstart & $C0=integer.
|
||||
(AB5A) CMP #$C0 ;Integer in ROM?
|
||||
BNE TOFILNOT ;No.
|
||||
(AB5E) JMP LNGNOTAV ;Yes - handle language-not-available error.
|
||||
-------------
|
||||
|
||||
TOFILNOT JMP FILENOT ;Handle file-not-found error.
|
||||
(AB61) ------------
|
||||
|
||||
* Fill in the FM work area buffer.
|
||||
* (Routine common to opening a new
|
||||
* or pre-existing file.)
|
||||
(ABA6)
|
||||
FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec).
|
||||
STA FIRSTSTK
|
||||
LDA FIL1TSSC,X ;T/S list sec val (from directory sec).
|
||||
STA FIRTSSEC
|
||||
LDA FIL1TYPE,X ;File type (from directory sec).
|
||||
STA FILTYPFM
|
||||
STA FILTYPWA
|
||||
LDA FIL1SIZE,X ;File size (from directory sec).
|
||||
STA FILENSEC
|
||||
LDA FIL1SIZE+1,X
|
||||
STA FILENSEC+1
|
||||
STX BYTNXDIR ;Index into directory sec to description.
|
||||
LDA #$FF ;Pretend that the last data sector used had
|
||||
STX RELPREV ;a relative sector number (in relation to
|
||||
(ABCF) STA RELPREV+1 ;the entire file) of #$FFFF. NOTE: This
|
||||
;value is later used to trick the read and
|
||||
;write subfunctions into ignoring the data
|
||||
;sector currently in memory.
|
||||
(ABD2) LDA MXIN1TSL ;Dictate that a T/S list can only describe $7A
|
||||
(ABD5) STA MXSCURTS ;(#122) data sectors. Note: This value is later
|
||||
;used by the read and write subfunctions to decide
|
||||
;whether or not the T/S list currently in memory
|
||||
;should be used.
|
||||
|
||||
* Read first T/S list sector
|
||||
* to the T/S list buffer.
|
||||
(ABD8) CLC ;(c) = 0 = signal 1rst T/S list sector.
|
||||
(ABD9) JMP READTS ;Go read in the T/S list sector.
|
||||
------------
|
||||
|
||||
* Read T/S list sector.
|
||||
(AF5E)
|
||||
READTS PHP ;Save (c) denoting if 1rst T/S list or not.
|
||||
;(c) = 0 = read 1rst T/S list sec.
|
||||
;(c) = 1 = read next T/S list sec.
|
||||
(AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is
|
||||
;required. (If T/S list buf has changed
|
||||
;since last read or write, then write it
|
||||
;back to the disk so don't overwrite buf
|
||||
;and lose information when read the new
|
||||
;T/S list sector.)
|
||||
|
||||
* Check if T/S list requires updating.
|
||||
* (ie. Has T/S list buf changed since
|
||||
* the last read or write?)
|
||||
(AF34)
|
||||
CKTSUPDT LDA UPDATFLG
|
||||
BMI WRITETS ;If bit 7 set, updating is required.
|
||||
(AF39) RTS ;NOT APPLICABLE TO THE DELETE FUNCTION.
|
||||
============
|
||||
|
||||
(AF62) JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list.
|
||||
|
||||
* Prepare RWTS's IOB for reading
|
||||
* or writing the T/S list sector.
|
||||
(AF4B)
|
||||
SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM
|
||||
STA IBBUFP ;parameter list & designate T/S list buf
|
||||
LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
|
||||
LDY CURTSSEC
|
||||
(AF5D) RTS
|
||||
|
||||
(AF65) JSR SELTSBUF ;Select the T/S list buffer.
|
||||
|
||||
* Point A4L/H at the T/S list sector buffer.
|
||||
(AF0C)
|
||||
SELTSBUF LDX #2 ;Index for T/S list buf.
|
||||
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from
|
||||
STA A4L ;the FM parameter list & put it in the
|
||||
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AF68) PLP ;Get saved (c) back from stack.
|
||||
(AF69) BCS RDNXTTS ;If (c) = 1, already read first T/S list
|
||||
;sec, so go read next one.
|
||||
;(Not applicable at this point in time cause (c) = 0.)
|
||||
|
||||
* Read first T/S list sector.
|
||||
* (Carry was clear.)
|
||||
(AF6B)
|
||||
RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec.
|
||||
LDY FIRTSSEC
|
||||
(AF71) JMP RDTSLST ;Go read T/S list sector into buffer.
|
||||
------------
|
||||
|
||||
* Subroutine to read/write T/S list sector.
|
||||
(AFB5)
|
||||
RDTSLST LDA #1 ;Read opcode for RWTS.
|
||||
|
||||
* Code common to read/write T/S list.
|
||||
(AFB7)
|
||||
RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y)
|
||||
STY CURTSSEC ;become current T/S list trk/sec values.
|
||||
(AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S list.
|
||||
|
||||
* Read or write the current T/S list.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Update the FM work area
|
||||
* (not in DOS buffer chain).
|
||||
(AFC0) LDY #5 ;Offset into current T/S list buffer.
|
||||
LDA (A4L),Y ;Get & save the relative sector number of
|
||||
(AFC4) STA RELFIRST ;the first data sector described in this
|
||||
;T/S list.
|
||||
(AFC7) CLC ;Add maximum # of data secs that can be described
|
||||
ADC MXSCURTS ;in this T/S list ($7A or #122).
|
||||
STA RELASTP1 ;Store relative sector number (plus 1) of
|
||||
INY ;the last data sector that can be described in list.
|
||||
LDA (A4L),Y
|
||||
STA REFIRST+1
|
||||
ADC MXSCURTS+1
|
||||
STA RELASTP1+1
|
||||
CLC ;Return with "no error" signal.
|
||||
(AFDB) RTS
|
||||
============
|
||||
|
||||
(AD2E) LDX CURDIRNX ;(x) = index to file description entry in
|
||||
;the directory sector buffer.
|
||||
(AD31) LDA FIL1TYPE,X ;Get file type from the directory sec buf.
|
||||
BPL ALTRNTRY ;Branch if file is not locked.
|
||||
(AD36) JMP FILELOKD ;Err - can't DELETE a locked file so go
|
||||
------------ ;handle error and exit.
|
||||
|
||||
* Get the track number of the file's first
|
||||
* T/S list from the file description entry
|
||||
* in the directory sec buf. Put it in the
|
||||
* work area and write it over the last char
|
||||
* position in the appropriate file name field
|
||||
* in the directory sector.
|
||||
(AD39)
|
||||
ALTRNTRY LDX CURDIRNX ;(x) = index to the file description entry
|
||||
;in the directory sector buffer.
|
||||
(AD3C) LDA FIL1TSTK,X ;Get the trk # of the first T/S list sec.
|
||||
STA FIRSTSTK ;Copy it into the work area and into the
|
||||
(AD42) STA FIL1NAME+29,X ;last character position of the file
|
||||
;name field description.
|
||||
(AD45) LDA #$FF ;Replace the original track # of the T/S
|
||||
STA FIL1TSTK,X ;list with #$FF to signal file is deleted.
|
||||
LDY FIL1TSSC,X ;Put the sector # of the file's first T/S
|
||||
STY FIRTSSEC ;list sec in the work area.
|
||||
(AD50) JSR WRDIRECT ;Write the modified directory sector.
|
||||
|
||||
* Write the directory buffer.
|
||||
(B037)
|
||||
WRDIRECT JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as the I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sec buf
|
||||
STA IBBUFP ;in the FM constants table.
|
||||
LDA ADRDIRBF+1 ;Store it in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
(B051) RTS
|
||||
|
||||
(B03A) LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec vals.
|
||||
LDY CURDIRSC
|
||||
LDA #2 ;Write opcode for RWTS.
|
||||
(B042) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer.
|
||||
------------
|
||||
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Read the T/S list sector into the
|
||||
* T/S list buffer. (Need this info
|
||||
* so know what sectors to release.)
|
||||
(AD53) CLC ;(c) = 0 = 1rst T/S list sec.
|
||||
(AD54) ;(c) = 1 = 2nd T/S list sec.
|
||||
RDTS4DEL JSR READTS ;Go read in a T/S list sector.
|
||||
|
||||
* Read T/S list sector.
|
||||
(AF5E)
|
||||
READTS PHP ;Save (c) denoting if 1rst T/S list or not.
|
||||
;(c) = 0 = read 1rst T/S list sec.
|
||||
;(c) = 1 = read next T/S list sec.
|
||||
(AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is
|
||||
;required. (If T/S list buf has changed
|
||||
;since last read or write, then write it
|
||||
;back to the disk so don't overwrite buf
|
||||
;and lose information when read the new
|
||||
;T/S list sector.)
|
||||
|
||||
* Check if T/S list requires updating.
|
||||
* (ie. Has T/S list buf changed since
|
||||
* the last read or write?)
|
||||
(AF34)
|
||||
CKTSUPDT LDA UPDATFLG
|
||||
(AF37) BMI WRITETS ;If bit 7 set, updating is required.
|
||||
;NOT APPLICABLE TO THE DELETE FUNCTION.
|
||||
(AF39) RTS
|
||||
|
||||
(AF62) JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list.
|
||||
|
||||
* Prepare RWTS's IOB for reading
|
||||
* or writing the T/S list sector.
|
||||
(AF4B)
|
||||
SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM
|
||||
STA IBBUFP ;parameter list & designate T/S list buf
|
||||
LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
|
||||
LDY CURTSSEC
|
||||
(AF5D) RTS
|
||||
|
||||
(AF65) JSR SELTSBUF ;Select the T/S list buffer.
|
||||
|
||||
* Point A4L/H at the T/S list sector buffer.
|
||||
(AF0C)
|
||||
SELTSBUF LDX #2 ;Index for T/S list buf.
|
||||
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from
|
||||
STA A4L ;the FM parameter list & put it in the
|
||||
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AF68) PLP ;Get saved (c) back from stack.
|
||||
(AF69) BCS RDNXTTS ;If (c) = 1, already read first T/S list
|
||||
;sec, so go read next one.
|
||||
;(Not applicable on first entry cause (c) = 0).
|
||||
|
||||
* Read first T/S list sector.
|
||||
* (Carry was clear.)
|
||||
(AF6B)
|
||||
RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec.
|
||||
LDY FIRTSSEC
|
||||
(AF71) JMP RDTSLST ;Go read T/S list sector into buffer.
|
||||
------------
|
||||
|
||||
* Read the next T/S list sector.
|
||||
* (Carry was set.)
|
||||
(AF74)
|
||||
RDNXTTS LDY #1 ;Index into the T/S list buffer.
|
||||
LDA (A4L),Y ;Trk for link to next T/S list sector.
|
||||
(AF78) BEQ TSLNKZRO ;Link zeroed out so there are no more
|
||||
;T/S list secs for this file.
|
||||
(AF7A) TAX ;(x) = next T/S list sec number.
|
||||
INY
|
||||
LDA (A4L),Y ;Sector # for link to next T/S list sec.
|
||||
TAY ;(y) = next T/S list sector number.
|
||||
(AF7F) JMP RDTSLST ;Go read in the next T/S list.
|
||||
-------------
|
||||
|
||||
* The T/S link zeroed out so we must decide
|
||||
* if we got an error or not. (That is, do
|
||||
* we want to create another T/S list?)
|
||||
(AF82)
|
||||
TSLNKZRO LDA OPCODEFM ;Check if reading or writing to see
|
||||
CMP #4 ;if we want to add another T/S list.
|
||||
(AF87) BEQ UPDATETS ;Writing - so go update link.
|
||||
;(Never take with DELETE function.)
|
||||
(AF89) SEC ;We were reading and the link zeroed out,
|
||||
(AF8A) RTS ;so return with (c) = 1 to generate an error.
|
||||
============ ;(Remember, we previously set the return
|
||||
;code to a default value for a file-not-found
|
||||
;error.)
|
||||
|
||||
* Subroutine to read/write T/S list sector.
|
||||
(AFB5)
|
||||
RDTSLST LDA #1 ;Read opcode for RWTS.
|
||||
|
||||
* Code common to read/write T/S list.
|
||||
(AFB7)
|
||||
RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y)
|
||||
STY CURTSSEC ;become current T/S list trk/sec values.
|
||||
(AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S
|
||||
;list.
|
||||
|
||||
* Read or write the current T/S list.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Update the FM work area
|
||||
* (not in DOS buffer chain).
|
||||
(AFC0) LDY #5 ;Offset into current T/S list buffer.
|
||||
LDA (A4L),Y ;Get & save the relative sector number of
|
||||
(AFC4) STA RELFIRST ;the first data sector that can be described in this
|
||||
;T/S list. (Possible values are: $0000, $007A,
|
||||
;2*$007A, 3*$007A OR 4*$007A.)
|
||||
(AFC7) CLC ;Add the maximum # of data secs that can be described
|
||||
ADC MXSCURTS ;in this T/S list.
|
||||
STA RELASTP1 ;Store maximum relative sector number (plus 1) of
|
||||
INY ;the last data sector that can be described in this list.
|
||||
LDA (A4L),Y
|
||||
STA RELFIRST+1
|
||||
ADC MXSCURTS+1
|
||||
(AFD7) STA RELASTP1+1 ;(RELASTP1/+1 = $0000, $007A, 2*$007A,
|
||||
;4*$007A or 5*$007A.)
|
||||
(AFDA) CLC ;Return with "no error" signal.
|
||||
(AFDB) RTS
|
||||
|
||||
(AD57) BCS DONEDEL ;Branch if just read the last T/S list
|
||||
;sector associated with this file.
|
||||
(AD59) JSR SELTSBUF ;Point A4L/H at the T/S list sector
|
||||
|
||||
|
||||
* Point A4L/H at the T/S list sector buffer.
|
||||
(AF0C)
|
||||
SELTSBUF LDX #2 ;Index for T/S list buf.
|
||||
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from
|
||||
STA A4L ;the FM parameter list & put it in the
|
||||
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
* Free all the sectors that are listed in
|
||||
* the T/S list sector that currently occupies
|
||||
* the T/S list sector buffer.
|
||||
(AD5C) LDY #12 ;First data sector pair listed is offset 12
|
||||
;bytes from the start of the T/S list buf.
|
||||
DELFREE STY CURDIRNX ;Set (y) = index to data pair in the
|
||||
(AD5E) ;T/S list buffer.
|
||||
(AD61) LDA (A4L),Y ;Get trk # of the data sector.
|
||||
(AD63) BMI BYPASDEL ;Neg track # is illegal (usually denotes
|
||||
;a deleted file). (Can use neg track # as a
|
||||
;protection scheme.)
|
||||
(AD65) BEQ BYPASDEL ;Trk # of 0 = no more data secs listed in
|
||||
;the current T/S list sector.
|
||||
(AD67) PHA ;Save trk # of data sector on the stack.
|
||||
INY ;Get sec # of data sector.
|
||||
LDA (A4L),Y
|
||||
TAY ;Condition (y) = sec & (a) = trk for entry
|
||||
PLA ;into routines to free up sectors.
|
||||
(AD6D) JSR FREESEC ;Free up sectors for the deleted file.
|
||||
|
||||
* Subroutine to free up a sector
|
||||
* in the VTOC TRKMAP.
|
||||
(AD89)
|
||||
FREESEC SEC ;(c) = 1 so free up present sector when
|
||||
;start rotating the assignment map.
|
||||
(AD8A) JSR SUB2FREE ;Adjust assignment map to FREE UP SECTORS
|
||||
;BY SETTING BIT corresponding to the sector
|
||||
;number. Next, merge ASIGNMAP with the
|
||||
;appropriate bit map in the VTOC.
|
||||
|
||||
* Subroutine to free up sectors that were
|
||||
* deleted or prematurely assigned but not used.
|
||||
*
|
||||
* This tricky little routine is easy to
|
||||
* understand once you realize that:
|
||||
* 1) Unlike the VTOC, ASIGNMAP does not
|
||||
* contain any unnecessarily assigned
|
||||
* sectors.
|
||||
* 2) If the disk was just written to,
|
||||
* ASIGNMAP does not house any newly
|
||||
* assigned sectors (even if those sectors
|
||||
* are necessary or not).
|
||||
* 3) Sectors are normally assigned in
|
||||
* descending order.
|
||||
* 4) The number of ROR's done = number
|
||||
* of sectors that need to be assigned.
|
||||
* For example: If the last track had never
|
||||
* been assigned and only sectors $0F and
|
||||
* $0E were needed, then on entry to SUB2FREE,
|
||||
* the first two bytes would appear as follows:
|
||||
* Sector numbers: CBA98765 43210FED
|
||||
* Bit values: 11111111 11111...
|
||||
* After the first ROR, the status of sector
|
||||
* $0D is determined by the entry status of
|
||||
* the carry (c):
|
||||
* Sector numbers: DCBA9876 543210FE
|
||||
* Bit values: c1111111 111111..
|
||||
* On the next ROR, the "CPY SECPERTK"
|
||||
* instruction conditions (c) to clear for
|
||||
* sector $0E:
|
||||
* Sector numbers: EDCBA987 6543210F
|
||||
* Bit values: 0c111111 1111111.
|
||||
* On the next ROR, the "CPY SECPERTK"
|
||||
* instruction conditions (c) to clear for
|
||||
* sector $0F:
|
||||
* Sector numbers: FEDCBA98 76543210
|
||||
* Bit values: 00c11111 11111111
|
||||
* When ASIGNMAP is merged with the corresponding
|
||||
* TRKMAP in the VTOC, the sectors that were
|
||||
* unnecessarily assigned in the VTOC are
|
||||
* freed. (Note: When used in the DELETE
|
||||
* function, SUB2FREE is repeatedly called
|
||||
* up by FREESEC to free one sector at a time.)
|
||||
(B2DD)
|
||||
SUB2FREE LDX #$FC ;Set index to shift 4 bytes as a unit
|
||||
(B2DF) ;(#$FC --> #$FF).
|
||||
STNDARD ROR ASIGNMAP-$FC,X ;4 bytes = map for 1 track.
|
||||
INX
|
||||
BNE STNDARD
|
||||
(B2E5) INY ;When (y) = 16, ASIGNMAP is back in
|
||||
;standard position.
|
||||
(B2E6) CPY SECPERTK ;Condition (c) for next shift.
|
||||
BNE SUB2FREE
|
||||
ASL ;Trk*4 to index TRKMAP.
|
||||
ASL
|
||||
TAY
|
||||
(B2EE) BEQ SUB2RTN ;Track value of 0 not allowed.
|
||||
|
||||
* ASIGNMAP now reflects the true sector assignment
|
||||
* and is in standard position. Therefore, merge it
|
||||
* with the appropriate TRKMAP in the VTOC to free up
|
||||
* extra sectors.
|
||||
(B2F0) LDX #4
|
||||
MERGMAPS LDA ASIGNMAP-1,X
|
||||
ORA TRKMAP0+3,Y ;Do the merge.
|
||||
STA TRKMAP0+3,Y
|
||||
DEY ;Reduce indices.
|
||||
DEX
|
||||
BNE MERGMAPS
|
||||
SUB2RTN RTS
|
||||
(B2FF)
|
||||
|
||||
(AD8D) LDA #0 ;Zero out ASIGNSEC, ASIGNTRK & ASIGNMAP
|
||||
LDX #5 ;(6 bytes) in the work area.
|
||||
RELEASEC STA ASIGNSEC,X
|
||||
DEX
|
||||
BPL RELEASEC
|
||||
(AD97) RTS
|
||||
|
||||
(AD70)
|
||||
BYPASDEL LDY CURDIRNX ;Set (y) to index the first data pair.
|
||||
INY ;Kick up (y) to point at next data pair.
|
||||
INY
|
||||
(AD75) BNE DELFREE ;If (y) < > 0, then never ran off the end of
|
||||
;the T/S list buff yet, so go check if more
|
||||
;data pairs to do.
|
||||
|
||||
* Free up the sector that contains
|
||||
* the T/S list sector.
|
||||
(AD77) LDA CURTSTRK ;Trk # of current T/S list sec.
|
||||
LDY CURTSSEC ;Sec # of current T/S list sec.
|
||||
(AD7D) JSR FREESEC ;Go free up the T/S list sec.
|
||||
|
||||
* Subroutine to free up a sector
|
||||
* in the VTOC TRKMAP.
|
||||
(AD89)
|
||||
FREESEC SEC ;(c) = 1 so free up present sector when
|
||||
;start rotating the assignment map.
|
||||
(AD8A) JSR SUB2FREE ;Adjust assignment map to FREE UP SECTORS
|
||||
;BY SETTING BIT corresponding to the sector
|
||||
;number. Next, merge ASIGNMAP with the
|
||||
;appropriate bit map in the VTOC.
|
||||
|
||||
(B2DD)
|
||||
SUB2FREE .
|
||||
.
|
||||
(See dis'mbly above.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AD8D) LDA #0 ;Zero out ASIGNSEC, ASIGNTRK & ASIGNMAP
|
||||
LDX #5 ;(6 bytes) in the work area.
|
||||
RELEASEC STA ASIGNSEC,X
|
||||
DEX
|
||||
BPL RELEASEC
|
||||
(AD97) RTS
|
||||
|
||||
(AD80) SEC
|
||||
(AD81) BCS RDTS4DEL ;ALWAYS.
|
||||
|
||||
* Done freeing up all the sectors associated
|
||||
* with this file, so now write the modified
|
||||
* VTOC back to the disk.
|
||||
(AD83)
|
||||
DONEDEL JSR WRITVTOC
|
||||
|
||||
* Write the updated VTOC to the disk.
|
||||
(AFFB)
|
||||
WRITVTOC LDA #2 ;Write opcode for RWTS.
|
||||
|
||||
* Common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get the address of the VTOC from the
|
||||
STY IBBUFP ;FM constants table and designate it as
|
||||
LDY ADRVTOC+1 ;the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal to the
|
||||
LDY #0 ;trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer.
|
||||
------------
|
||||
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AD86) JMP GOODFMXT ;Go exit file manager cleanly.
|
||||
-----------
|
||||
|
||||
|
||||
* Exit the file manager with or without errors.
|
||||
(B35F)
|
||||
LNGNOTAV LDA #1
|
||||
(B361) BNE BADFMXIT ;ALWAYS.
|
||||
|
||||
(B373)
|
||||
FILENOT LDA #6
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.)
|
||||
NOP
|
||||
FILELOKD LDA #10
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
||||
|
||||
* Copy the FM work area (non-chain) to
|
||||
* the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list & put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;from the stack.
|
||||
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
||||
TXS ;caller of the function even if we are
|
||||
RTS ;several subroutines deeper than the
|
||||
============ ;original entry point. (That is, return to
|
||||
;AFTRFUNC ($A6AB) in the FMDRIVER routine
|
||||
;($A6A8).)
|
||||
|
416
textfiles.com/apple/ANATOMY/fninit.txt
Normal file
416
textfiles.com/apple/ANATOMY/fninit.txt
Normal file
@@ -0,0 +1,416 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* INIT function handler *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* The INIT function handler (FNINIT, $AEBE) is only called *
|
||||
* by the INIT command handler (CMDINIT, $A54F). The execution *
|
||||
* pattern of FNINIT is described in the preamble accompanying *
|
||||
* the formatted disassembly of the INIT command handler. *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
(AE8E)
|
||||
FNINIT JSR ZWRKAREA ;Initialize the work area.
|
||||
|
||||
* Zero out the FM work area so it can be customized
|
||||
* in accordance with the calling function.
|
||||
* (Although some work bytes may not be subsequently
|
||||
* altered, don't be lulled into thinking that they
|
||||
* are not important. Zero values are just as relevant
|
||||
* as non-zero values.)
|
||||
* (P.S. Don't confuse the FM work area with its
|
||||
* image (FM work buffer) that is housed in the
|
||||
* chain of DOS buffers.)
|
||||
(ABDC)
|
||||
ZWRKAREA LDA #0
|
||||
TAX ;Initialize the x-index.
|
||||
ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
|
||||
INX
|
||||
CPX #45 ;Work area is 45 bytes long.
|
||||
(ABE5) BNE ZEROWRKA
|
||||
|
||||
* Begin customizing the work area.
|
||||
* Get volume, drive, slot & catalog track
|
||||
* values from the FM parameter list. Put
|
||||
* drive, slot*16, catalog track and
|
||||
* complemented volume number in the work area.
|
||||
(ABE7) LDA VOLFM ;Volume number.
|
||||
EOR #$FF ;Calculate 1's complement of volume #.
|
||||
STA VOLWA
|
||||
LDA DRVFM ;Drive #.
|
||||
STA DRVWA
|
||||
LDA SLOTFM ;Get slot #.
|
||||
ASL ;Calculate slot * 16.
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
TAX ;Set (x) = slot * 16.
|
||||
STX SLOT16WA
|
||||
LDA #$11 ;Normal catalog trk = #17.
|
||||
STA TRKWA
|
||||
(AC05) RTS
|
||||
|
||||
(AE91) LDA #4 ;Opcode for format.
|
||||
|
||||
* Go format the disk.
|
||||
(AE93) JSR RWTSDRV1 ;Call RWTS driver to FORMAT the disk.
|
||||
|
||||
(B058)
|
||||
RWTSDRV1 .
|
||||
.
|
||||
(See dis'mbly of RWTSDRV1 using FORMAT.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Put volume, number of next track to be
|
||||
* assigned and assignment direction in the
|
||||
* VTOC sector buffer.
|
||||
(AE96) LDA VOLWA ;Complemented volume number (from work area).
|
||||
EOR #$FF ;Uncomplement it & put volume # in VTOC.
|
||||
STA VOLUSED
|
||||
LDA #$11 ;Use trk # 17 for catalog track.
|
||||
(AEA0) STA NXTRKUSE ;Set the catalog trk as the next track to
|
||||
;assign. (NXTRKUSE is located in the VTOC.)
|
||||
(AEA3) LDA #1 ;Assignment direction is forward.
|
||||
(AEA5) STA DRECTION
|
||||
|
||||
* Zero out the VTOC buffer from TRKMAP0 to
|
||||
* the end of the VTOC sector. (Note: This
|
||||
* allocates all tracks.)
|
||||
(AEA8) LDX #56 ;Offset to TRKMAP0 in the VTOC.
|
||||
LDA #0
|
||||
ZVTOC STA VTOCBUFF,X ;Zero out a TRKMAP byte.
|
||||
INX
|
||||
(AEB0) BNE ZVTOC
|
||||
|
||||
* Free up all tracks except tracks
|
||||
* 0, 1, 2 & catalog track (#17).
|
||||
*
|
||||
* NOTE: DOS only occupies sectors
|
||||
* 0 to 4 on track 2, but this routine
|
||||
* takes the rest of the sectors on
|
||||
* track 2 out of circulation.
|
||||
(AEB2) LDX #$0C ;Offset to start of trkmap3.
|
||||
FREETRK CPX #$8C ;Offset 1 past the end of TRKMAP34.
|
||||
BEQ FREEDTKS ;Done up to end of TRKMAP#$34?
|
||||
LDY #3 ;Initialize the index to the end of FRETKMSK.
|
||||
FREEIT LDA FRETKMSK,Y ;Free most TRKMAPs. (Starting with
|
||||
(AEBA) ;TRKMAP3.) NOTE: Not freeing up VTOC
|
||||
;sector or tracks used by DOS.
|
||||
(AEBD) STA TRKMAP0,X ;Free tracks by placing the following bytes
|
||||
;in each TRKMAP: "FF FF 00 00".
|
||||
(AEC0) INX ;Kick up index to byte in TRKMAP.
|
||||
(AEC1) DEY ;Reduce index to FRETKMSK cause loading from
|
||||
;the end of FRETKMSK: "00 00 FF FF".
|
||||
(AEC2) BPL FREEIT ;(4 bytes/TRKMAP & 4 bytes/FRETKMSK)
|
||||
CPX #$44 ;Offset to start of TRKMAP17 (ie. cat trk).
|
||||
(AEC6) BNE FREETRK ;Have we freed trks 3 to 16 yet?
|
||||
;If not, take branch.
|
||||
(AEC8) LDX #$48 ;Offset to trk 18 (ie. skip the cat trk).
|
||||
BNE FREETRK ;ALWAYS - go free trks 18 to 34.
|
||||
FREEDTKS JSR WRITVTOC ;Write freed up VTOC to disk.
|
||||
(AECC)
|
||||
|
||||
* Write the Volume Table of Contents (VTOC).
|
||||
(AFFB)
|
||||
WRITVTOC LDA #2 ;Write opcode for RWTS.
|
||||
|
||||
* Common to read/write the VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get the address of the VTOC from the FM
|
||||
STY IBBUFP ;constants table & designate it as the
|
||||
LDY ADRVTOC+1 ;I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(x) = trk/sec values of
|
||||
LDY #0 ;the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call RWTS driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Clear out the directory sector buffer.
|
||||
(AECF) LDX #0
|
||||
TXA
|
||||
CLRDIREC STA DIRECBUF,X
|
||||
INX
|
||||
BNE CLRDIREC
|
||||
(AED8) JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as the I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sec buf
|
||||
STA IBBUFP ;in the FM constants table.
|
||||
LDA ADRDIRBF+1 ;Store it in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
(B051) RTS
|
||||
|
||||
(AEDB) LDA #$11 ;(a) = number of catalog track.
|
||||
LDY SECPERTK ;Number of sectors/track = 16.
|
||||
DEY
|
||||
DEY
|
||||
(AEE2) STA IBTRK ;Put catalog track in IOB.
|
||||
|
||||
* Write the directory sectors
|
||||
* (trk17, secs 15 to 1).
|
||||
(AEE5)
|
||||
SETLNKTK STA DIRLNKTK ;Set the trk/sec values for the link to the
|
||||
SETLNKSC STY DIRLNKSC ;next directory sector.
|
||||
INY ;Get the number of the sector to be written
|
||||
STY IBSECT ;and put it in RWTS's IOB.
|
||||
LDA #2 ;Write opcode for RWTS.
|
||||
(AEF1) JSR RWTSDRV1 ;Write the directory sector to the disk.
|
||||
|
||||
(B058)
|
||||
RWTSDRV1 .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AEF4) LDY DIRLNKSC ;Sector value of the next directory sec to write.
|
||||
DEY ;Kick it down (will increment it later).
|
||||
BMI DOIMAGE ;Don't do sector 0 cause that is the VTOC.
|
||||
BNE SETLNKSC ;Go write sectors 2 to 15.
|
||||
TYA
|
||||
(AEFD) BEQ SETLNKTK ;Go back to write sector 1 and zero out
|
||||
;the directory sector links.
|
||||
|
||||
* Routine to write the DOS image
|
||||
* on tracks 0 to 2.
|
||||
(AEFF)
|
||||
DOIMAGE JSR PRPWRDOS ;Get ready to write the DOS image.
|
||||
|
||||
* Set up RWTS's IOB to write DOS.
|
||||
(B7C2)
|
||||
PRPWRDOS LDA FIRDOSPG ;Designate the start of DOS as the address
|
||||
STA IBBUFP+1 ;of the I/O buffer in RWTS's IOB.
|
||||
LDA #0
|
||||
STA IBBUFP
|
||||
LDA VOLWA ;Complement the volume number.
|
||||
EOR #$FF
|
||||
STA IBVOL
|
||||
(B7D5) RTS
|
||||
|
||||
(AF02) JSR WRDOSIMG ;Write the DOS image
|
||||
|
||||
* Write the DOS image in trks 0 to 2.
|
||||
* That is, write trk02/sec04 ($B5FF) down
|
||||
* to trk00/sec0C ($9D00).
|
||||
(B74A)
|
||||
WRDOSIMG LDA BTSTAGE+1 ;Calculate the number of pages to write:
|
||||
SEC ; (#$B6 - #$9D = #$19 or #25).
|
||||
SBC IBBUFP+1
|
||||
STA BT2PGCTR ;Set counter for 25 pages.
|
||||
LDA BTSTAGE+1
|
||||
STA IBBUFP+1
|
||||
DEC IBBUFP+1 ;Start with page #$B5.
|
||||
LDA #2 ;Start with trk02/sec04.
|
||||
STA IBTRK
|
||||
LDA #4
|
||||
STA IBSECT
|
||||
LDA #2 ;Write opcode for RWTS.
|
||||
STA IBCMD
|
||||
(B76C) JSR RWPAGES ;Write trk2/sec4 to trk0/sec0.
|
||||
|
||||
* Read/write a group of pages.
|
||||
(B793)
|
||||
RWPAGES LDA ADROFIOB+1 ;Initialize (a)/(y) with hi/low bytes
|
||||
(B796) LDY ADROFIOB ;of the addr of RWTS's IOB for entry
|
||||
;into RWTS.
|
||||
(B799) JSR ENTERWTS ;Enter into RWTS to read/write a sector.
|
||||
|
||||
* Entry to RWTS.
|
||||
(B7B5) PHP ;Save status on stk.
|
||||
;(c) = 0 if seek or read.
|
||||
;(c) = 1 if write or format.
|
||||
(B7B6) SEI ;Set the interrupt disable flag to prevent
|
||||
;any further interrupts from occurring when
|
||||
;doing real-time programming.
|
||||
(B7B7) JSR RWTS ;Enter RWTS proper to do operation:
|
||||
; $00=seek, $01=read,
|
||||
; $02=write & $03=format.
|
||||
|
||||
* RWTS proper.
|
||||
(BD00)
|
||||
RWTS .
|
||||
.
|
||||
(See dis'mbly of RWTS in formatted
|
||||
dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B7BA) BCS ERRENTER ;Operation was not successful.
|
||||
PLP ;Throw status off the stack.
|
||||
CLC ;Signal operation was successful.
|
||||
(B7BE) RTS
|
||||
============
|
||||
|
||||
(B7BF)
|
||||
ERRENTER PLP ;Throw status off the stack.
|
||||
SEC ;Signal operation was unsuccessful.
|
||||
(B7C1) RTS
|
||||
============
|
||||
|
||||
(B79C) LDY IBSECT ;Get # of sector just read or written.
|
||||
(B79F) DEY ;Value for next sector to read/write
|
||||
;(when executing BOOT1, #$09 --> #$FF).
|
||||
(B7A0) BPL SAMETRK ;Branch to use the same track.
|
||||
|
||||
* Start a new track.
|
||||
(B7A2) LDY #$0F ;Start with sector 15.
|
||||
NOP
|
||||
NOP
|
||||
(B7A6) DEC IBTRK ;Reduce # of trk wanted.
|
||||
|
||||
* Adjust pointer to IOB and test if there
|
||||
* are any more sectors to read/write.
|
||||
(B7A9)
|
||||
SAMETRK STY IBSECT ;Store number of sector wanted.
|
||||
DEC IBBUFP+1 ;Reduce buffer's page address.
|
||||
(B7AF) DEC BT2PGCTR ;Reduce counter for # of pages
|
||||
;(ie. sectors) to read or write.
|
||||
(B7B2) BNE RWPAGES ;More sectors to read or write.
|
||||
(B7B4) RTS
|
||||
|
||||
* Write trk00/sec09 ($BFFF) down
|
||||
* to trk00/sec00 ($B600).
|
||||
(B76F) LDA BTSTAGE+1 ;Store hi byte of address of the
|
||||
STA IMG8D+1 ;start of Boot1 (#$B6).
|
||||
CLC ;Calulate the hi byte of the address of
|
||||
ADC #9 ;trk00/sec09 (#$B6 + #$09 = #$BF).
|
||||
STA IBBUFP+1 ;Set buffer to send info to page #$BF.
|
||||
LDA #10 ;Designate that there are 10 pages to
|
||||
STA BT2PGCTR ;write (#$BFFF - #$B600).
|
||||
SEC
|
||||
SBC #1
|
||||
(B783) STA IMG8FF ;Designate that 9 pages are to be read
|
||||
;when BOOT1 is executed.
|
||||
(B786) STA IBSECT ;Start writing with trk0/sec9.
|
||||
(B789) JSR RWPAGES ;Go write trk0/sec9 to trk0/sec0.
|
||||
|
||||
* Read/write a group of pages.
|
||||
(B793)
|
||||
RWPAGES LDA ADROFIOB+1 ;Initialize (a)/(y) with hi/low bytes
|
||||
(B796) LDY ADROFIOB ;of the addr of RWTS's IOB for entry
|
||||
;into RWTS.
|
||||
(B799) JSR ENTERWTS ;Enter into RWTS to read/write a sector.
|
||||
|
||||
* Entry to RWTS.
|
||||
(B7B5) PHP ;Save status on stk.
|
||||
;(c) = 0 if seek or read.
|
||||
;(c) = 1 if write or format.
|
||||
(B7B6) SEI ;Set the interrupt disable flag to prevent
|
||||
;any further interrupts from occurring when
|
||||
;doing real-time programming.
|
||||
(B7B7) JSR RWTS ;Enter RWTS proper to do operation:
|
||||
; $00=seek, $01=read,
|
||||
; $02=write & $03=format.
|
||||
|
||||
* RWTS proper.
|
||||
(BD00)
|
||||
RWTS .
|
||||
.
|
||||
(See dis'mbly of RWTS in formatted
|
||||
dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B7BA) BCS ERRENTER ;Operation was not successful.
|
||||
PLP ;Throw status off the stack.
|
||||
CLC ;Signal operation was successful.
|
||||
(B7BE) RTS
|
||||
=============
|
||||
|
||||
(B7BF)
|
||||
ERRENTER PLP ;Throw status off the stack.
|
||||
SEC ;Signal operation was unsuccessful.
|
||||
(B7C1) RTS
|
||||
============
|
||||
|
||||
(B79C) LDY IBSECT ;Get # of sector just read or written.
|
||||
(B79F) DEY ;Value for next sector to read/write
|
||||
;(when executing BOOT1, #$09 --> #$FF).
|
||||
(B7A0) BPL SAMETRK ;Branch to use the same track.
|
||||
|
||||
* Start a new track.
|
||||
(B7A2) LDY #$0F ;Start with sector 15.
|
||||
NOP
|
||||
NOP
|
||||
(B7A6) DEC IBTRK ;Reduce # of trk wanted.
|
||||
|
||||
* Adjust pointer to IOB and test if there
|
||||
* are any more sectors to read/write.
|
||||
(B7A9)
|
||||
SAMETRK STY IBSECT ;Store number of sector wanted.
|
||||
DEC IBBUFP+1 ;Reduce buffer's page address.
|
||||
(B7AF) DEC BT2PGCTR ;Reduce counter for # of pages to
|
||||
;read or write.
|
||||
(B7B2) BNE RWPAGES ;More sectors to read or write.
|
||||
(B7B4) RTS
|
||||
============
|
||||
|
||||
(B78C) RTS
|
||||
============
|
||||
|
||||
(AF05) JMP GOODFMXT ;Exit cleanly.
|
||||
------------
|
||||
|
||||
|
||||
* Exit the file manager.
|
||||
(B37F)
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
||||
|
||||
* Copy the FM work area (non-chain) to
|
||||
* the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list & put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE81) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;from the stack.
|
||||
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
||||
TXS ;caller even if we are several subroutines
|
||||
(B396) RTS ;deeper than the original entry point.
|
||||
============ ;(Returns to AFTRFUNC ($A6AB) in the
|
||||
;FMDRIVER routine ($A6A8).
|
1002
textfiles.com/apple/ANATOMY/fnopen.txt
Normal file
1002
textfiles.com/apple/ANATOMY/fnopen.txt
Normal file
File diff suppressed because it is too large
Load Diff
157
textfiles.com/apple/ANATOMY/fnposn.txt
Normal file
157
textfiles.com/apple/ANATOMY/fnposn.txt
Normal file
@@ -0,0 +1,157 @@
|
||||
*================================================================*
|
||||
* *
|
||||
* Position Function handler *
|
||||
* *
|
||||
*================================================================*
|
||||
* *
|
||||
* The position function handler (FNPOSN, $AD12) is simply *
|
||||
* used to adjust the filepointer. This function is used *
|
||||
* sparingly by DOS. As a matter of fact, FNPOSN is only called *
|
||||
* by READ (CMDREAD, $A510) and WRITE (CMDWRITE,$A51B) commands *
|
||||
* that are accompanied by R(ecord number) and/or B(yte) *
|
||||
* parameters. (Even the POSITION command does not use the *
|
||||
* position function.) In an earlier version of DOS 3.3, FNPOSN *
|
||||
* was used to back the file pointer up when a end-of-file marker *
|
||||
* was detected via the APPEND command. However, APPEND now *
|
||||
* adjusts the filepointer manually. *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
|
||||
|
||||
(AD12)
|
||||
FNPOSN JSR CALCFPTR ;Using R-, L-, & B-parameters, calculate
|
||||
;the position of the file pointer.
|
||||
|
||||
* Calculate the exact position of the three-byte file pointer:
|
||||
* FILPTSEC = sector offset (low/hi format) into entire file (2 bytes).
|
||||
* FILPTBYT = byte offset into current sector (1 byte).
|
||||
* All three bytes define the exact position of the file pointer
|
||||
* via the following formula:
|
||||
* (record number * record length) + byte offset into record
|
||||
* where: RECNMBFM = record number from R-parameter (set
|
||||
* by user when using random access files
|
||||
* or simply incremented when using other
|
||||
* file types).
|
||||
* RECLENWA = record length parsed from L-parameter
|
||||
* and assigned with open command (else
|
||||
* defaulted to a size of 1).
|
||||
* BYTOFFFM = offset into the current record (set by
|
||||
* user when using open command or
|
||||
* occassionally used with sequential files
|
||||
* as a B-parameter).
|
||||
* Note that you can actually directly access any byte in any
|
||||
* file by bypassing the command interpreter and setting the
|
||||
* L-, B- & R-parameters however you want.
|
||||
|
||||
(B300)
|
||||
CALCFPTR LDA RECNMBFM ;Put record # in multiplier and
|
||||
STA FILPTBYT ;also save it in the work area.
|
||||
STA RECNMBWA
|
||||
LDA RECNMBFM+1
|
||||
STA FILPTSEC
|
||||
STA RECNMBWA+1
|
||||
LDA #0 ;Zero out the hi order byte of the sector
|
||||
(B314) STA FILPTSEC+1 ;offset into the file.
|
||||
|
||||
* Calculate: Record number * record length.
|
||||
* This routine simply multiplies two 16-bit
|
||||
* numbers together. It may at first seem
|
||||
* confusing because FILPTSEC & FILPTBYT
|
||||
* are both used for holding the multiplier
|
||||
* (record #) and part of the product result.
|
||||
* However, the bits of the product don't get mixed
|
||||
* up with the bits of the multiplier because rolling
|
||||
* in a product bit also rolls out the last-used
|
||||
* multiplier bit (ie. there is no bit overlap).
|
||||
(B317) LDY #16 ;16 bits / one 2-byte number.
|
||||
NMBXLEN TAX ;Save part of running product.
|
||||
;(On first entry, set (x) = 0.)
|
||||
LDA FILPTBYT ;Set (a) = multiplier.
|
||||
LSR ;Put multiplier bit in carry.
|
||||
BCS NMBXLEN1 ;If (c)=1, go add multiplicand to running product.
|
||||
TXA ;(a) = part of running product.
|
||||
BCC NMBXLEN2 ;Always branch. No use adding multiplicand cause
|
||||
;bit of multiplier is 0. Therefore, just go shift
|
||||
;running product.
|
||||
NMBXLEN1 CLC ;Add multiplicand to running version of shifted product.
|
||||
LDA FILPTSEC+1
|
||||
ADC RECLENWA
|
||||
STA FILPTSEC+1
|
||||
TXA ;Set (a) = low byte of running product.
|
||||
ADC RECLENWA+1
|
||||
NMBXLEN2 ROR ;Shift the running product (as a unit) 1 bit
|
||||
ROR FILPTSEC+1 ;position right for next time around.
|
||||
ROR FILPTSEC ;Shift lower 2 bytes of running product and
|
||||
ROR FILPTBYT ;at the same time throw out the last-used
|
||||
;multiplier bit.
|
||||
DEY ;Reduce bit counter.
|
||||
(B33C) BNE NMBXLEN ;Branch if haven't done all 16 bits yet.
|
||||
|
||||
* Copy byte offset into record from
|
||||
* the FM parameter list to the work area.
|
||||
(B33E) CLC
|
||||
LDA BYTOFFFM
|
||||
(B342) STA BYTOFFWA
|
||||
|
||||
* Calculate lowest order byte of file pointer.
|
||||
* BYTOFFWA = offset into current record.
|
||||
* = byte offset into record
|
||||
* + (record length * record number).
|
||||
(B345) ADC FILPTBYT
|
||||
STA FILPTBYT
|
||||
LDA BYTOFFFM+1
|
||||
STA BYTPFFWA+1
|
||||
ADC FILPTSEC
|
||||
STA FILPTSEC
|
||||
BCC CALCRTS
|
||||
INC FILPTSEC+1
|
||||
CALCRTS RTS
|
||||
(B35C)
|
||||
|
||||
(AD15) JMP GOODFMXT ;Go exit the file manager.
|
||||
------------
|
||||
|
||||
(B37F)
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0 ;Avoid that infamous $48 bug.
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy work area to the work buffer.
|
||||
|
||||
* Copy the FM work area buffer (non-chain)
|
||||
* to the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select FM work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list and put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;back from the stack.
|
||||
(B392) LDX STKSAV ;Adjust the stack pointer to force exit
|
||||
TXS ;to the caller of the function even if we
|
||||
(B396) RTS ;are presently several subroutines deeper
|
||||
============ ;than the original entry point. (Returns
|
||||
;to AFTRFUNC ($A6AB) in the FMDRIVER routine
|
||||
;($A6A8).)
|
654
textfiles.com/apple/ANATOMY/fnrename.txt
Normal file
654
textfiles.com/apple/ANATOMY/fnrename.txt
Normal file
@@ -0,0 +1,654 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* RENAME function handler *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* The RENAME function handler (FNRENAME, $AC3A) uses the *
|
||||
* COMNOPEN routine ($AB28) to locate the desired file. COMNOPEN *
|
||||
* configures the FM work area, reads in a fresh VYOC and then *
|
||||
* searches the directory sectors for the file description entry *
|
||||
* of the wanted file. (The links to the first directory sector *
|
||||
* are housed in the VTOC. Each subsequent directory sector *
|
||||
* contains the links to the next directory sector. The link *
|
||||
* bytes of the last directory sector are zeroed out.) *
|
||||
* Each directory contains up to seven different file *
|
||||
* descriptions. An example of the data contained in a file *
|
||||
* description is shown below: *
|
||||
* FIL1TSTK DS 1 ;Track # of first T/S list for file 1. *
|
||||
* FIL1TSSC DS 1 ;Sector # of first T/S list for file 1. *
|
||||
* FIL1TYPE DS 1 ;File type code for file 1. ($00=Text, *
|
||||
* ;$01=Integer, $02=Applesoft, $04=Binary, *
|
||||
* ;$08=S-type, $10=Relocatable, $20=A-type *
|
||||
* ;and $40=B-type.) The hi bit is set on *
|
||||
* ;locked files. For example, $02=unlocked *
|
||||
* ;Applesoft and $82=locked Applesoft. *
|
||||
* FIL1NAME DS 30 ;Name of file 1. If a file name less than *
|
||||
* ;30 bytes is used, trailing spaces are *
|
||||
* ;added to the name to fill the buffer. *
|
||||
* FIL1SIZE DS 2 ;Size of file 1 in terms of the number of *
|
||||
* ;sectors used. *
|
||||
*(If a file was deleted, the track # of the first T/S list sec *
|
||||
* was copied to the last byte position of the name field. The *
|
||||
* original track # byte (FIL1TSTK) was then overwritten with *
|
||||
* an #$FF.) *
|
||||
* As each directory sector is read in, an attempt is made *
|
||||
* to locate a file description which contains the name of the *
|
||||
* file wanted. If the name can't be located after seaching all *
|
||||
* the directories, a second search is made to locate the first *
|
||||
* available space in a directory sector where a new file *
|
||||
* description can be placed (in case the command can create a *
|
||||
* new file). If no free space is located, a disk-full error *
|
||||
* message is printed. *
|
||||
* If an available space is located, NEWDESCRP ($B2C1) copies *
|
||||
* the name of the wanted file from the primary file name buffer *
|
||||
* (PRIMFNBF, $AA75) into the new entry space. A check is then *
|
||||
* made to see if the command can legally create a new file. The *
|
||||
* identifying command byte (NDX2CMD, $AA5F) is used to index a *
|
||||
* table of command attributes (CMDATTRB, $A909). Because bit0 *
|
||||
* of the first attribute byte associated with the RENAME command *
|
||||
* is clear, a new file cannot legally be created. As a result, *
|
||||
* the RENAME command is exited with a file-not-found message. *
|
||||
* If a (non-deleted) description entry containing the name *
|
||||
* of the wanted file is located, execution branches to the *
|
||||
* FILLINWA routine ($ABA6). FILLINWA uses the information *
|
||||
* contained in the description entry to customize the FM work *
|
||||
* area. Eventhough it is not needed for the RENAME function, *
|
||||
* the first T/S list belonging to the wanted file is read in *
|
||||
* (READTS, $A5FE). Next, the file type code is checked. The *
|
||||
* RENAME command is aborted with a file-locked message if the hi *
|
||||
* bit of the file code byte is set. *
|
||||
* If the file is not locked, the A4L/H pointer ($42,$43) *
|
||||
* are loaded with the address of the rename buffer (RENAMBUF, *
|
||||
* $B5BD) and NEWDESCRP ($B2C1) is called to copy the new name *
|
||||
* from the secondary name buffer (SCNDFNBF, $AA93) to the *
|
||||
* name field in the file description entry. After WRDIRECT *
|
||||
* ($B037) is called to write the modified directory sector back *
|
||||
* to the disk, execution returns to the RENAME command handler. *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
(AC3A)
|
||||
FNRENAME JSR COMNOPEN ;Locate a file with the same name & open it.
|
||||
|
||||
*** NOTE ***
|
||||
* Not all of the common open routine is
|
||||
* listed below because not all of it
|
||||
* applies to the RENAME function.
|
||||
|
||||
* Common open routine.
|
||||
(AB28)
|
||||
COMNOPEN JSR ZWRKAREA ;Initialize the work area.
|
||||
|
||||
* Zero out the FM work area so it can be customized
|
||||
* in accordance with the calling function.
|
||||
* (Although some work bytes may not be subsequently
|
||||
* altered, don't be lulled into thinking that they
|
||||
* are not inportant. Zero values are just as relevant
|
||||
* as non-zero values.)
|
||||
* (P.S. Don't confuse the FM work area with its image
|
||||
* (FM work buffer) that is housed in the chain of
|
||||
* DOS buffers.)
|
||||
(ABDC)
|
||||
ZWRKAREA LDA #0
|
||||
TAX ;Initialize the x-index.
|
||||
ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
|
||||
INX
|
||||
CPX #45 ;Work area is 45 bytes long.
|
||||
(ABE5) BNE ZEROWRKA
|
||||
|
||||
* Begin customizing the work area.
|
||||
* Get volume, drive, slot & catalog track
|
||||
* values from the FM parameter list. Put
|
||||
* drive, slot*16, catalog track and
|
||||
* complemented volume number in the work area.
|
||||
(ABE7) LDA VOLFM ;Volume number.
|
||||
EOR #$FF ;Calculate 1's complement of volume #.
|
||||
STA VOLWA
|
||||
LDA DRVFM ;Drive #.
|
||||
STA DRVWA
|
||||
LDA SLOTFM ;Get slot #.
|
||||
ASL ;Calculate slot * 16.
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
TAX ;Set (x) = slot * 16.
|
||||
STX SLOT16WA
|
||||
LDA #$11 ;Normal catalog trk = #17.
|
||||
STA TRKWA
|
||||
(AC05) RTS
|
||||
|
||||
(AB2B) LDA #1 ;Describe sector length as 256 bytes
|
||||
(AB2D) STA SECSIZWA+1 ;(in the FM work area).
|
||||
|
||||
* Get record length from the FM parameter
|
||||
* list & put it in the FM work area.
|
||||
* (Don't allow a zero length. If zero,
|
||||
* change it to one.)
|
||||
(AB30) LDX RECLENFM+1
|
||||
LDA RECLENFM
|
||||
BNE STRECLEN ;Non-zero record length is ok.
|
||||
CPX #0
|
||||
BNE STRECLEN
|
||||
INX ;Was zero, make it one instead.
|
||||
STRECLEN STA RECLENWA ;Put length in FM work area.
|
||||
STX RECLENWA+1
|
||||
(AB43) JSR GETFNTRY ;Try to find a directory sector for the file.
|
||||
|
||||
* Locate or create a file entry in the
|
||||
* directory buffer.
|
||||
* Make two searches if necessary:
|
||||
* - Search1 - try to locate entry with same name as file wanted.
|
||||
* - Search2 - couldn't locate entry corresponding to file
|
||||
* wanted so create a new entry in first available
|
||||
* space in the directory sector.
|
||||
(B1C9)
|
||||
GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to
|
||||
;TRKMAPS & to the first directory sector.
|
||||
|
||||
* Read the Volume Table of Contents (VTOC).
|
||||
(AFF7)
|
||||
READVTOC LDA #1 ;Read opcode for RWTS.
|
||||
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
||||
|
||||
* Code common to read/write VTOC.
|
||||
(AFFD)
|
||||
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
||||
STY IBBUFP ;FM constants table & designate it
|
||||
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STY IBBUFP+1
|
||||
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
||||
LDY #0 ;to the trk/sec values of the VTOC.
|
||||
(B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC.
|
||||
------------
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dism'bly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Point A4L/H at the primary file name buffer.
|
||||
(B1CC) LDA FNAMBUFM ;Get address of the name buffer from the
|
||||
STA A4L ;FM parameter list & put it in the A4L/H
|
||||
LDA FNAMBUFM+1 ;pointer.
|
||||
(B1D4) STA A4L+1
|
||||
|
||||
* Try to find the directory sector with the
|
||||
* wanted file name & read it into the directory
|
||||
* sector buffer. Make two searches if necessary.
|
||||
* On the first search, try to find a matching name.
|
||||
* If that doesn't work, do a second search to store
|
||||
* the description in the first available file
|
||||
* description field in a directory sector in case
|
||||
* the command can create a new file.
|
||||
(B1D6) LDA #1 ;Initialize the search counter (SCRNSRCH)
|
||||
SETSRCH STA SCRNSRCH ;in the FM scratch space for two searches.
|
||||
(B1D8) ;(1 = search1, 0 = search2)
|
||||
(B1DB) LDA #0 ;Initialize offset of file description from
|
||||
STA SECNXDIR ;the very first directory sector.
|
||||
CLC ;(c)=0=signal to read first directory sec.
|
||||
GETDIRSC INC SECNXDIR ;Kick up offset from first directory.
|
||||
(B1E4) JSR RDDIRECT ;Go read directory sector into buffer.
|
||||
|
||||
* Read a directory sector.
|
||||
(B011)
|
||||
RDDIRECT PHP ;Save (c) on stack:
|
||||
; (c) = 0 = read 1rst directory sector.
|
||||
; (c) = 1 = read next directory sector.
|
||||
(B012) JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get addr of direc
|
||||
STA IBBUFP ;sec buf from the
|
||||
LDA ADRDIRBF+1 ;FM constants tbl
|
||||
STA IBBUFP+1 ;& designate it as
|
||||
(B051) RTS ;as the I/O buffer.
|
||||
|
||||
(B015) PLP ;Check if 1rst directory sec or not.
|
||||
(B016) BCS RDNXTDIR ;Go read next directory sector.
|
||||
|
||||
* Read the first directory sector.
|
||||
* (Carry = 0.)
|
||||
(B018)
|
||||
RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory
|
||||
LDX FIRDIRTK ;sector (from the VTOC buffer).
|
||||
(B01E) BNE DODIRRD ;ALWAYS - go read in directory sector.
|
||||
|
||||
* Read the next directory sector.
|
||||
* (Carry = 1.)
|
||||
(B020)
|
||||
RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
(B023) BNE GETDIRLK ;Link not zeroed out.
|
||||
SEC ;Link zeroed out - exit with (c) = 1 to
|
||||
(B026) RTS ;signal there are no more directory secs.
|
||||
============
|
||||
|
||||
(B027)
|
||||
GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the
|
||||
;link in the current directory sector.
|
||||
|
||||
* Call to read in the directory sector.
|
||||
(B02A)
|
||||
DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that
|
||||
(B02D) STY CURDIRSC ;we are about to read so they will be
|
||||
;the current directory sec values for the
|
||||
;next time around.
|
||||
(B030) LDA #1 ;Read opcode for RWTS.
|
||||
(B032) JSR RWTSDRVR ;Call RWTS driver to do the read.
|
||||
|
||||
* Read/Write Track/Sector driver.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(B035) CLC ;Link didn't zero out so signal that there
|
||||
(B036) RTS ;are more directory secs to read & exit.
|
||||
============
|
||||
|
||||
(B1E7) BCS CHNGSRCH ;Link zeroed out, no more directory secs,
|
||||
;so go switch searches.
|
||||
(B1E9) LDX #0
|
||||
CKDIRTRK STX CURDIRNX ;Offset of file description into the current
|
||||
(B1EB) ;directory sector.
|
||||
(B1EE) LDA FIL1TSTK,X ;Get track number of first T/S list sec
|
||||
;for a particular file from the file
|
||||
;description entry in the directory sector.
|
||||
(B1F1) BEQ CHRSRCHA ;If trk=0, no more files in this direc sec.
|
||||
(B1F3) BMI CHRSRCHB ;Skip deleted file. (When a file is
|
||||
;deleted, #$FF is put in byte where trk #
|
||||
;of first T/S list is usually kept.
|
||||
|
||||
* Compare the name found in the file
|
||||
* description entry portion of the
|
||||
* directory sector with the file name
|
||||
* wanted. (On entry, A4L/H points at
|
||||
* the primary file name buffer.)
|
||||
(B1F5) LDY #0 ;Initialize index to file name buffer.
|
||||
INX ;Point (x) at the first char position
|
||||
INX ;in the name field of description entry.
|
||||
CMPNAMES INX
|
||||
LDA (A4L),Y ;Get char of name from primary.
|
||||
CMP FIL1TSTRK,X ;Compare to char in description name.
|
||||
BNE DONTMTCH ;Chars (and therefore names) don't match.
|
||||
INY
|
||||
CPY #30 ;Done all chars yet (0 to 29)?
|
||||
BNE CMPNAMES ;Chars matched, branch if more to check.
|
||||
LDX CURDIRNX ;All chars matched, so names matched.
|
||||
CLC ;Return with (x) = index to file
|
||||
(B20A) RTS ;description in current directory sector
|
||||
============ ;and with (c) = 0 to signal that the
|
||||
;correct file description was found.
|
||||
|
||||
* Advance index to point at the next
|
||||
* potential file description entry.
|
||||
(B20B)
|
||||
DONTMTCH JSR NXPLUS35 ;Names didn't match, so adjust index
|
||||
;to point at the next entry.
|
||||
|
||||
* Add 35 to the offset to point the index
|
||||
* at the next file description entry.
|
||||
* (Check to make sure that we don't index
|
||||
* right off the end of the directory sec.)
|
||||
(B230)
|
||||
NXPLUS35 CLC
|
||||
LDA CURDIRNX
|
||||
(B234) ADC #35 ;Add 35 to index. (Each file description
|
||||
;entry is 35 bytes long.)
|
||||
(B236) TAX ;Check if there is more space for entries
|
||||
CPX #245 ;in the current directory sector.
|
||||
(B239) RTS ;Exit with (c) conditioned:
|
||||
; (c) = 0 = more space in directory.
|
||||
; (c) = 1 = ran off end of directory.
|
||||
|
||||
(B20E) BCC CKDIRTRK ;More potential file descriptions to check
|
||||
;in this directory sector.
|
||||
(B210) BCS GETDIRSC ;Go get next directory sector.
|
||||
------------
|
||||
|
||||
* If we just completed first search,
|
||||
* go back to do second search.
|
||||
(B212)
|
||||
CHRSRCHA LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B215) BNE SETSRCH ;Go switch to second search.
|
||||
|
||||
* If first search, skip deleted files.
|
||||
* If second search, fall through to store
|
||||
* the description in the first unused
|
||||
* space in the directory.
|
||||
(B217)
|
||||
CHRSRCHB LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
(B21A) BNE DONTMTCH
|
||||
|
||||
* Couldn't locate the named file in the
|
||||
* directory description entries, so begin
|
||||
* creating a new description in the first
|
||||
* available space in a directory (in case
|
||||
* command can legally create a new file).
|
||||
(B21C)
|
||||
NWDESCRP LDY #0 ;Initialize index to primary file name buffer.
|
||||
INX ;Set index to first char position in the
|
||||
INX ;name field of the file description entry
|
||||
SETNWNAM INX ;space in the directory sector.
|
||||
LDA (A4L),Y ;Copy char from primary file name buffer
|
||||
STA FIL1TSTK,X ;to the directory description space.
|
||||
INY
|
||||
CPY #30 ;30 chars in name (0 to 29).
|
||||
BNE SETNWNAM ;Branch if more chars to copy.
|
||||
LDX CURDIRNX ;Return with (x) = index to file
|
||||
SEC ;description space in current directory
|
||||
(B22F) RTS ;sector & with (c)=1 to signal new entry
|
||||
============ ;was just created.
|
||||
|
||||
* If first search, switch to second search.
|
||||
* If second search, link zeroed out because
|
||||
* there isn't enough room left on the
|
||||
* disk for a new entry. Therefore,
|
||||
* exit with a disk-full error message.
|
||||
(B23A)
|
||||
CHNGSRCH LDA #0 ;Used to reset search counter if
|
||||
;go back to do start second search.
|
||||
(B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
||||
BNE SETSRCH ;Just did first search, so go start second search.
|
||||
(B241) JMP DISKFULL ;Even second search was unsuccesful so go
|
||||
------------ ;handle a disk-full error.
|
||||
|
||||
(AB46) BCC FILLINWA ;Branch if found a directory sector with
|
||||
;name wanted in the file description entry.
|
||||
|
||||
* Named file wasn't found in directory,
|
||||
* so prepare a new file entry in case
|
||||
* command can legally create a new file.
|
||||
(AB48) STX CURDIRNX ;Offset to new description entry in
|
||||
;case want to create a new file.
|
||||
|
||||
* Check to see if command can
|
||||
* legally create a new file.
|
||||
(AB4B) LDX NDX2CMD ;(x) = index representing command.
|
||||
(AB4E) LDA CMDATTRB,X ;Get first byte containing description
|
||||
;of the given command's attributes.
|
||||
(AB51) LDX CURDIRNX ;(x) = index for new file description
|
||||
;entry into the directory sector.
|
||||
(AB54) LSR ;(c) = bit 0 of 1rst attribute byte.
|
||||
(AB55) BCS CREATNEW ;If (c) = 1, command can create a new file.
|
||||
;FALL THRU FOR RENAME FUNCTION (cause (c) = 0).
|
||||
|
||||
* Command can't create a new file.
|
||||
* See which language we are using and
|
||||
* exit with the appropriate error msg.
|
||||
(AB57)
|
||||
NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM),
|
||||
;$80=coldstart & $C0=integer.
|
||||
(AB5A) CMP #$C0 ;Integer in ROM?
|
||||
BNE TOFILNOT ;No.
|
||||
(AB5E) JMP LNGNOTAV ;Yes - handle language-not-available error.
|
||||
------------
|
||||
|
||||
TOFILNOT JMP FILENOT ;Handle file-not-found error.
|
||||
(AB61) ------------
|
||||
|
||||
*** NOTE ***
|
||||
* ALTHOUGH IT IS NOT NEEDED FOR THE RENAME
|
||||
* FUNCTION, THE T/S LIST SECTOR IS AUTOMATICALLY
|
||||
* READ INTO THE T/S LIST BUFFER IF THE FILE IS FOUND.
|
||||
|
||||
* Fill in the FM work area buffer.
|
||||
* (Routine common to opening a new
|
||||
* or pre-existing file.)
|
||||
(ABA6)
|
||||
FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec).
|
||||
STA FIRSTSTK
|
||||
LDA FIL1TSSC,X ;T/S list sec val (from directory sec).
|
||||
STA FIRTSSEC
|
||||
LDA FIL1TYPE,X ;File type (from directory sec).
|
||||
STA FILTYPFM
|
||||
STA FILTYPWA
|
||||
LDA FIL1SIZE,X ;File size (from directory sec).
|
||||
STA FILENSEC
|
||||
LDA FIL1SIZE+1,X
|
||||
STA FILENSEC+1
|
||||
STX BYTNXDIR ;Index into directory sec to description.
|
||||
LDA #$FF ;Pretend that the last data sector used had a
|
||||
STX RELPREV ;relative sector number (in relation to
|
||||
(ABCF) STA RELPREV+1 ;the entire file) of #$FFFF. NOTE: This
|
||||
;value is later used to trick the read and
|
||||
;write subfunctions into ignoring the data
|
||||
;sector currently in memory.
|
||||
(ABD2) LDA MXIN1TSL ;Dictate that a T/S list can only describe $7A
|
||||
(ABD5) STA MXSCURTS ;(#122) data sectors. Note: This value is later
|
||||
;used by the read and write subfunctions to decide
|
||||
;whether or not the T/S list currently in memory
|
||||
;should be used.
|
||||
|
||||
* Read first T/S list sector
|
||||
* to the T/S list buffer.
|
||||
(ABD8) CLC ;(c) = 0 = signal 1rst T/S list sector.
|
||||
(ABD9) JMP READTS ;Go read in the T/S list sector.
|
||||
------------
|
||||
|
||||
* Read T/S list sector.
|
||||
(AF5E)
|
||||
READTS PHP ;Save (c) denoting if 1rst T/S list or not.
|
||||
;(c) = 0 = read 1rst T/S list sec.
|
||||
;(c) = 1 = read next T/S list sec.
|
||||
(AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is
|
||||
;required. (If T/S list buf has changed
|
||||
;since last read or write, then write it
|
||||
;back to the disk so don't overwrite buf
|
||||
;and lose information when read the new
|
||||
;T/S list sector.)
|
||||
|
||||
* Check if T/S list requires updating.
|
||||
* (ie. Has T/S list buf changed since
|
||||
* the last read or write?)
|
||||
(AF34)
|
||||
CKTSUPDT LDA UPDATFLG
|
||||
(AF36) BMI WRITETS ;If bit 7 set, updating is required.
|
||||
;NOT APPLICABLE TO THE RENAME FUNCTION.
|
||||
(AF39) RTS
|
||||
============
|
||||
|
||||
(AF62) JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list.
|
||||
|
||||
* Prepare RWTS's IOB for reading
|
||||
* or writing the T/S list sector.
|
||||
(AF4B)
|
||||
SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM
|
||||
STA IBBUFP ;parameter list & designate T/S list buf
|
||||
LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
|
||||
LDY CURTSSEC
|
||||
(AF5D) RTS
|
||||
|
||||
(AF65) JSR SELTSBUF ;Select the T/S list buffer.
|
||||
|
||||
* Point A4L/H at the T/S list sector buffer.
|
||||
(AF0C)
|
||||
SELTSBUF LDX #2 ;Index for T/S list buf.
|
||||
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from
|
||||
STA A4L ;the FM parameter list & put it in the
|
||||
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AF68) PLP ;Get saved (c) back from stack.
|
||||
(AF69) BCS RDNXTTS ;If (c) = 1, already read first T/S list
|
||||
;sec, so go read next one.
|
||||
;BRANCH NOT APPLICABLE TO RENAME FUNCTION (cause (c) = 0).
|
||||
|
||||
* Read first T/S list sector.
|
||||
* (Carry was clear.)
|
||||
(AF6B)
|
||||
RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec.
|
||||
LDY FIRTSSEC
|
||||
(AF71) JMP RDTSLST ;Go read T/S list sector into buffer.
|
||||
------------
|
||||
|
||||
* Subroutine to read/write T/S list sector.
|
||||
(AFB5)
|
||||
RDTSLST LDA #1 ;Read opcode for RWTS.
|
||||
|
||||
* Code common to read/write T/S list.
|
||||
(AFB7)
|
||||
RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y)
|
||||
STY CURTSSEC ;become current T/S list trk/sec values.
|
||||
(AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write the
|
||||
;current T/S list.
|
||||
|
||||
* Read or write the current T/S list.
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using READ or WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
* Update the FM work area
|
||||
* (not in DOS buffer chain).
|
||||
(AFC0) LDY #5 ;Offset into current T/S list buffer.
|
||||
LDA (A4L),Y ;Get & save the relative sector number of
|
||||
(AFC4) STA RELFIRST ;the first data sector described in this
|
||||
;T/S list.
|
||||
(AFC7) CLC ;Add maximum # of data secs that can
|
||||
ADC MXSCURTS ;possibly be described in this T/S list.
|
||||
STA RELASTP1 ;Store maximum relative sector number (plus 1) of
|
||||
INY ;the last data sector that can be described in list.
|
||||
LDA (A4L),Y
|
||||
STA RELFIRST+1
|
||||
ADC MXSCURTS+1
|
||||
STA RELASTP1+1
|
||||
CLC ;Return with "no error" signal.
|
||||
(AFDB) RTS
|
||||
|
||||
(AC3D) LDA FILTYPWA ;Get the file type (from the FM work area).
|
||||
BMI TOFILOCK ;Error - can't rename a locked file.
|
||||
LDA RENAMBUF ;Get the address of the SECONDARY FILE NAME
|
||||
STA A4L ;from the FM parameter list & put it in the
|
||||
LDA RENAMBUF+1 ;A4L/H pointer.
|
||||
STA A4L+1
|
||||
LDX CURDIRNX ;(x) = index into the current directory sec.
|
||||
(AC4F) JSR NWDESCRP ;COPY THE NEW NAME FROM THE SECONDARY NAME
|
||||
;BUFFER TO THE DIRECTORY SECTOR BUFFER.
|
||||
|
||||
(B21C)
|
||||
NEWDSCRP LDY #0 ;Initialize index to name buffer.
|
||||
INX ;Set index to first char position in the name field
|
||||
INX ;of the file description entry in the directory sector.
|
||||
SETNWNAM INX
|
||||
LDA (A4L),Y ;Get char from the name buffer.
|
||||
STA FIL1TSTK,X ;Put it in the name field of file description
|
||||
INY ;space in the directory sector.
|
||||
CPY #30 ;30 chars in name (0 to 29).
|
||||
BNE SETNWNAM ;More chars to copy.
|
||||
LDX CURDIRNX ;Return with index pointing to the file
|
||||
SEC ;description entry space in the current
|
||||
(B22F) RTS ;directory sector and with (c) = 1 to signal a new entry
|
||||
;was created (when not using RENAME function).
|
||||
|
||||
(AC52) JSR WRDIRECT ;Write the modified directory sector to the disk.
|
||||
|
||||
* Write the directory buffer.
|
||||
(B037)
|
||||
WRDIRECT JSR PT2DIRBF
|
||||
|
||||
* Designate the directory sector buffer
|
||||
* as the I/O buffer in RWTS's IOB.
|
||||
(B045)
|
||||
PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sec buf
|
||||
STA IBBUFP ;in the FM constants table.
|
||||
LDA ADRDIRBF+1 ;Store it in RWTS's IOB.
|
||||
STA IBBUFP+1
|
||||
(B051) RTS
|
||||
|
||||
(B03A) LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec vals.
|
||||
LDY CURDIRSC
|
||||
LDA #2 ;Write opcode for RWTS.
|
||||
(B042) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer.
|
||||
------------
|
||||
|
||||
(B052)
|
||||
RWTSDRVR .
|
||||
.
|
||||
(See dis'mbly of RWTS driver using WRITE.)
|
||||
.
|
||||
.
|
||||
(RTS)
|
||||
|
||||
(AC55) JMP GOODFMXT ;Exit the file manager cleanly.
|
||||
------------
|
||||
|
||||
(AC6D)
|
||||
TOFILOCK JMP FILELOKD
|
||||
------------
|
||||
|
||||
|
||||
* Exit the file manager with or without errors.
|
||||
(B35F)
|
||||
LNGNOTAV LDA #1
|
||||
(B361) BNE BADFMXIT ;ALWAYS.
|
||||
|
||||
(B373)
|
||||
FILENOT LDA #6
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.)
|
||||
NOP
|
||||
FILELOKD LDA #10
|
||||
BNE BADFMXIT ;ALWAYS.
|
||||
GOODFMXT LDA RTNCODFM
|
||||
CLC ;(c) = 0 to signal good operation.
|
||||
BCC FMEXIT
|
||||
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
||||
FMEXIT PHP ;Save status on stack.
|
||||
STA RTNCODFM ;Store return code in FM parameter list.
|
||||
LDA #0
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
||||
|
||||
* Copy the FM work area (non-chain) to
|
||||
* the FM work buffer (in DOS chain).
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
||||
|
||||
* Point the A4L/H pointer at the FM work buffer.
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Set index to select work buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
||||
STA A4L ;FM parameter list & put it in the pointer.
|
||||
LDA WRKBUFFM+1,X
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
(AE81) LDY #0 ;Initialize index.
|
||||
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
||||
STA (A4L),Y ;Put it in the work buffer.
|
||||
INY
|
||||
CPY #45 ;45 bytes to copy (0 to 44).
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Retrieve status of success of operation
|
||||
;from the stack.
|
||||
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
||||
TXS ;caller even if we are several subroutines
|
||||
(B396) RTS ;deeper than the original entry point.
|
||||
============ ;(Normally returns to AFTRFUNC ($A6AB)
|
||||
;located in the FMDRIVER routine ($A6A8).)
|
1029
textfiles.com/apple/ANATOMY/fnverify.txt
Normal file
1029
textfiles.com/apple/ANATOMY/fnverify.txt
Normal file
File diff suppressed because it is too large
Load Diff
1074
textfiles.com/apple/ANATOMY/psnrdone.txt
Normal file
1074
textfiles.com/apple/ANATOMY/psnrdone.txt
Normal file
File diff suppressed because it is too large
Load Diff
1113
textfiles.com/apple/ANATOMY/psnrdrng.txt
Normal file
1113
textfiles.com/apple/ANATOMY/psnrdrng.txt
Normal file
File diff suppressed because it is too large
Load Diff
1180
textfiles.com/apple/ANATOMY/psnwrone.txt
Normal file
1180
textfiles.com/apple/ANATOMY/psnwrone.txt
Normal file
File diff suppressed because it is too large
Load Diff
1219
textfiles.com/apple/ANATOMY/psnwrrng.txt
Normal file
1219
textfiles.com/apple/ANATOMY/psnwrrng.txt
Normal file
File diff suppressed because it is too large
Load Diff
178
textfiles.com/apple/ANATOMY/references.txt
Normal file
178
textfiles.com/apple/ANATOMY/references.txt
Normal file
@@ -0,0 +1,178 @@
|
||||
DOS 3.3 ANATOMY - REFERENCES
|
||||
|
||||
Command Handlers can be found in the CMDS folder. Function
|
||||
Handlers can be found in the FN folder. Everything else can be
|
||||
found in the MISC folder.
|
||||
|
||||
This text file series of 'DOS 3.3 Anatomy could not have been
|
||||
completed without review and use of several excellent
|
||||
references. Because DOS 3.3 utilizes monitor ROM
|
||||
($F800-$FFFF) and is designed to support the Applesoft
|
||||
language ($D000-$F7FF), a diverse array of sources were
|
||||
consulted. Some, but not all, of the references and sources
|
||||
used are listed below.
|
||||
|
||||
Apple Computer, Inc. 1979. Apple II Reference Manual. Apple
|
||||
Computer Inc. Cupertino, California.
|
||||
|
||||
----------. 1980. The DOS Manual: Disk Operating System. Apple
|
||||
Computer Inc. Cupertino, California.
|
||||
|
||||
----------. 1981. Apple II Monitors Peeled. Apple Computer Inc.
|
||||
Cupertino, California.
|
||||
|
||||
----------. 1984. The Apple II Reference Manual. Volumes 1 and
|
||||
2. Apple Computer Inc. Cupertino, California.
|
||||
|
||||
----------. 1985. Apple IIe Technical Reference Manual. Apple
|
||||
Computer Inc. Cupertino, California.
|
||||
|
||||
----------. 1985. Apple IIc Reference Manual. Apple Computer
|
||||
Inc. Cupertino, California.
|
||||
|
||||
Apple PugetSound Program Library Exchange. 1981. Call-A.P.P.L.E.
|
||||
In Depth (1): All About Applesoft. A Call-A.P.P.L.E. Extra.
|
||||
Apple PugetSound Program Library Exchange, Renton, Washington.
|
||||
- Should be required reading for any Applesoft BASIC
|
||||
programmer. (Apple PugetSound Program Library Exchange has
|
||||
since changed its name to A.P.P.L.E. CO-OP).
|
||||
|
||||
---------. 1981. Call-A.P.P.L.E. In Depth (3): All About DOS.
|
||||
A Call-A.P.P.L.E. Extra. Apple PugetSound Program Library
|
||||
Exchange, Renton, Washington.
|
||||
- Like the previous reference listed, this book lives up to
|
||||
its name. Although some of the articles are now dated,
|
||||
this reference is still very useful.
|
||||
|
||||
Bredon, Glen. 1984. MERLIN: The Macro Assembler for the Apple.
|
||||
Roger Wagner Publishing, Inc. Santee, California.
|
||||
- A high quality 6502 assembler.
|
||||
- Contains a utility and a series of text files for producing
|
||||
a commented source code listing of Applesoft BASIC.
|
||||
|
||||
Cavallari, Ford. 1982. MICRO on the Apple Vol. 3 (DOS 3.3)
|
||||
MICRO Ink, Inc. Chelm, Massachusetts.
|
||||
|
||||
East, M.L. and F.B. East. 1985. Programmers' Handbook of
|
||||
Computer Printer Commands. Cardinal Point Incorporated.
|
||||
Ellettsville, Indiana.
|
||||
|
||||
----------. 1986. Programmers' Handbook of Computer Printer
|
||||
Commands-II. Cardinal Point Incorporated. Ellettsville, Indiana.
|
||||
|
||||
Luebbert, W. F. 1981. What's Where in the Apple: A Complete
|
||||
Guide to the Apple Computer for the Apple II, Apple II Plus &
|
||||
Apple IIe. Including: the Atlas & the Gazetteer. MICRO Ink, Inc.
|
||||
Chelmsford, Massachusetts.
|
||||
- Should be in every BASIC and assembly language programmer's
|
||||
library.
|
||||
|
||||
Mossberg, S. 1983. Disassembly Lines Volume I. MicroSPARC,
|
||||
Inc. Concord, Massachusetts.
|
||||
|
||||
----------. 1984. Disassembly Lines Volume II. MicroSPARC,
|
||||
Inc. Concord, Massachusetts.
|
||||
- Both this and the previous reference are a compendium of
|
||||
articles published in Nibble magazine (MicroSPARC Inc.)
|
||||
under the byline of "Disassembly Lines".
|
||||
- These articles represent a linear disassembly of most
|
||||
routines in DOS 3.3. In addition, sections of Applesoft
|
||||
are also disassembled. In keeping with the Mossberg
|
||||
tradition, these references are of very high quality.
|
||||
As usual, Mossberg continues to amaze and reveal.
|
||||
|
||||
|
||||
Sather, J. 1983. Understanding the Apple II. Quality Software.
|
||||
Chatsworth, California.
|
||||
- Mainly a hardware/firmware manual that should appeal to
|
||||
those knowledgeable in electronics. Lesser mortals may
|
||||
find some sections difficult to comprehend. However, most
|
||||
assembly language programmers should be able to understand
|
||||
the sections related to the DOS 3.3 operating system.
|
||||
These sections contain information that can easily be
|
||||
translated into protection techniques such as half- and
|
||||
quarter-tracking.
|
||||
|
||||
|
||||
S-C Software Corporation. 1980. Apple Assembly Line. S-C
|
||||
Software Corporation. Dallas, Texas.
|
||||
- A newsletter dedicated to the assembly language programmer.
|
||||
- Contains all kinds of information on programming techniques
|
||||
and the DOS 3.3 and PRODOS operating systems. A high
|
||||
quality publication that should be in the library of any
|
||||
6502 assembly language programmer.
|
||||
|
||||
----------. 1982. S-C Docu-Mentor for Applesoft. S-C Software
|
||||
Corporation. Dallas, Texas.
|
||||
- Heavily commented Applesoft source code on a disk.
|
||||
|
||||
SoftKey Publishing. 1981. Hardcore Computist. Softkey
|
||||
Publishing. Tacoma, Washington. (This magazine has undergone
|
||||
several name changes since its inception.)
|
||||
- AN old classic (now-defunct) magazine, provides detailed
|
||||
protection techniques and trick DOS. Dedicated assembly
|
||||
language programmers may find some articles frustrating
|
||||
because many programs appear to be geared toward users
|
||||
who want to copy protected disks by using a recipe
|
||||
consisting of machine language embedded in Applesoft
|
||||
programs. Because the machine code is often housed in data
|
||||
statements, it is frequently necessary to disassemble the
|
||||
machine code and reformat the BASIC programs in order to
|
||||
understand the techniques being used. Less use of decimal
|
||||
machine code and more use of assembly language would prove
|
||||
useful to assembly language programmers that aren't into
|
||||
copying disks but are instead interested in programming
|
||||
techniques related to protection. This publication carries
|
||||
information not available elsewhere.
|
||||
|
||||
Wagner, R. 1982. Assembly Lines: The Book. A Beginner's Guide
|
||||
to 6502 Programming on the Apple II. Softalk Publishing.
|
||||
Hollywood, California.
|
||||
- One of the few books that provides a good introduction to
|
||||
assembly language for novice programmers but at the same
|
||||
time is a valuable reference for the more experienced
|
||||
programmer. Elementary techniques for accessing DOS from
|
||||
assembly language are described.
|
||||
- This reference is now available from Penguin Software,
|
||||
Geneva, Illinois.
|
||||
|
||||
Weisharr, T. ----. DOStalk. Softalk Publishing Incorporated.
|
||||
Hollywood, California.
|
||||
- A regular column that appeared in the now-defunct Softalk
|
||||
magazine.
|
||||
- Although remnants of this magazine are hard to find, two of
|
||||
its former columnists have teamed up to solve the problem.
|
||||
Kersey (of Beagle Brothers fame) and Weisharr have
|
||||
coauthored The DOStalk Scrapbook. This reference is
|
||||
apparently a polished up, reorganized version of their
|
||||
previous DOStalk articles. Recommended for anybody thats
|
||||
interested in DOS 3.3. The DOStalk Scrapbook is available
|
||||
from Tab Books, Blue Ridge Summit, Pennsylvania.
|
||||
|
||||
----------. 1985. Open-Apple. Overland Park, Kansas.
|
||||
- Newsletter designed to "fill one of the information voids
|
||||
left by Softalk's demise". A rare breed of publication
|
||||
that is not only down to earth and humurous, but more
|
||||
importantly, it consistently maintains a balance of topics
|
||||
that appeal to both novice programmers as well as
|
||||
professional software authors.
|
||||
|
||||
Worth, D. and P. Lechner. 1981. Beneath Apple DOS. Quality
|
||||
Software. Reseda, California.
|
||||
- Best described as a true classic.
|
||||
- Should be in the library of any serious assembly language
|
||||
programmer using DOS 3.3.
|
||||
|
||||
----------. 1981. Bag of Tricks. Quality Software. Reseda,
|
||||
California.
|
||||
- Information contained in the instruction manual is was
|
||||
worth the price of the entire software package.
|
||||
|
||||
Special thanks go to the following for source validation
|
||||
references, comments and interpretation; Windsor Scientific,
|
||||
Steve Wozniak and Glen Bredon.
|
||||
|
||||
|
||||
|
||||
|
||||
|
1174
textfiles.com/apple/ANATOMY/rwts.d1.format.txt
Normal file
1174
textfiles.com/apple/ANATOMY/rwts.d1.format.txt
Normal file
File diff suppressed because it is too large
Load Diff
771
textfiles.com/apple/ANATOMY/rwts.drvr.seek.txt
Normal file
771
textfiles.com/apple/ANATOMY/rwts.drvr.seek.txt
Normal file
@@ -0,0 +1,771 @@
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
* *
|
||||
* RWTSDRVR using SEEK *
|
||||
* *
|
||||
*----------------------------------------------------------------*
|
||||
* *
|
||||
* Just as the file manager is used to manipulate entire *
|
||||
* files at once, RWTS reads or writes disk data one sector at a *
|
||||
* time. The software interface between these two levels of DOS *
|
||||
* management is represented by the RWTS driver routines *
|
||||
* (RWTSDRVR, $B052 and RWTSDRV1, $B058). RWTSDRVR is called any *
|
||||
* time the file manager wants to seek a given track or read or *
|
||||
* write a sector of disk data. This routine is always entered *
|
||||
* with the accumulator containing the RWTS opcode ($00=seek, *
|
||||
* $01=read, $03=write) and the x- and y-registers housing the *
|
||||
* target track and sector values. Although RWTSDRV1 is only *
|
||||
* directly called via the INIT function handler (with the *
|
||||
* accumlator containing the format ($04) opcode), execution *
|
||||
* falls into RWTSDRV1 from RWTSDRVR. The driver routines check *
|
||||
* to see if data are to be output to the disk and condition the *
|
||||
* carry flag accordingly. The carry is set if the format or *
|
||||
* write opcodes are detected. After setting up RWTS's parameter *
|
||||
* list (also known as an input/output block, IOB), the driver *
|
||||
* calls ENTERWTS ($B7B5). *
|
||||
* ENTERWTS preserves the conditioned carry flag by pushing *
|
||||
* the status register on the stack. Next the interrupt disable *
|
||||
* flag is set to prevent any maskable interrupts from interfer- *
|
||||
* ring with the real-time subroutines employed by RWTS. *
|
||||
* Finally, ENTERWTS calls RWTS proper ($BD00) to do the desired *
|
||||
* function. Execution eventually returns to the ENTERWTS *
|
||||
* routine at $B7BA. The saved status byte is thrown off the *
|
||||
* stack, the carry flag is cleared or set (depending on whether *
|
||||
* or not RWTS encountered an error) and then execution returns *
|
||||
* to the caller of ENTERWTS. *
|
||||
* After updating the last-used volume value in the FM *
|
||||
* parameter list, the RWTSDRV1 routine checks the carry flag to *
|
||||
* see if RWTS detected an error. If an error was encountered, *
|
||||
* the carry is reset and execution returns to the calling *
|
||||
* routine via ERRWTSDR ($B0A1). If no error was detected, the *
|
||||
* "BCS ERRWTSDR" instruction at $B09E is skipped and execution *
|
||||
* returns to the caller of the driving routine with the carry *
|
||||
* clear. *
|
||||
* Note that ENTERWTS is the one and only DIRECT caller of *
|
||||
* RWTS. THE DOS MANUAL recommends the following procedure be *
|
||||
* employed to call RWTS from an assembly language program: *
|
||||
* 1) Set up the IOB and DCT tables accordingly. *
|
||||
* 2) Load the y-register and accumulator with the low and *
|
||||
* high bytes (respectively) of the address of the IOB. *
|
||||
* 3) JSR to $3D9. (The instruction at $3D9 normally *
|
||||
* contains a jump to ENTERWTS.) *
|
||||
* The execution pattern of RWTS and its associated sub- *
|
||||
* routines is long, but not particularly complex. On the one *
|
||||
* hand RWTS is rather simple because it can only perform four *
|
||||
* types of functions (seek, read, write or format). However, *
|
||||
* many people find RWTS difficult to understand because: *
|
||||
* 1) It is the only portion of DOS that uses time-critical *
|
||||
* code. *
|
||||
* 2) Two different methods are used to encode information *
|
||||
* on the disk. *
|
||||
* 3) The actual method by which the read/write head is *
|
||||
* moved to different track positions on the disk is not *
|
||||
* well publicized. *
|
||||
* Time critical code and data encoding information are clearly *
|
||||
* explained in chapter 3 of BENEATH APPLE DOS. (When reading *
|
||||
* this reference, you may find it elcudiating to keep in mind *
|
||||
* that some protected disks (such as LOCKSMITH by ALPHA LOGIC *
|
||||
* BUSINESS SYSTEMS) modify the read/write routines to EOR each *
|
||||
* sector of data with its sector number.) *
|
||||
* *
|
||||
* The positioning of the read/write head is the only *
|
||||
* function of the seek command. Positioning actually occurs in *
|
||||
* the SEEKIT routine ($BE6B). The seek command is described in *
|
||||
* the disassembly given below. Because the following source *
|
||||
* code is very highly commented and because most of it is common *
|
||||
* to all of RWTS's functions, you are urged to read the follow- *
|
||||
* ing disassembly over carefully a few times. A quicker under- *
|
||||
* standing may be achieved if you keep the following information *
|
||||
* in mind: *
|
||||
* - Data are written on the disk in 35 circular paths or *
|
||||
* concentric circles called tracks. Track $00 is located at *
|
||||
* the outer edge of the disk, whereas track $22 (#34) is *
|
||||
* represented by the innermost concentric circle. Each track *
|
||||
* is divided into 16 segments ($00 to $0F) called sectors. *
|
||||
* - A disk controller card can be used in any peripheral slot *
|
||||
* except slot $00. Each of the remaining seven slots ($01 to *
|
||||
* $07) can contain a controller card. Two different drives *
|
||||
* can be operated from one controller card. Therefore, you *
|
||||
* can hang up to 14 different drives from a single Apple II, *
|
||||
* II+ or IIe machine. *
|
||||
* - The disk controller ROM is relocatable and is copied into *
|
||||
* the computer's memory at $Cs00 to $CsFF (where s = slot *
|
||||
* number). All drive functions are performed by indirectly *
|
||||
* referencing base addrs $C000 to $C00F. The motor-on-off, *
|
||||
* drive selection and read-write switches are indexed with an *
|
||||
* offset equal to slot * 16. The four different stepper motor *
|
||||
* magnets are all referenced via the $C080 base addr. The *
|
||||
* index used = (slot*16)+bits0and1 of halftrack# + carry. The *
|
||||
* slot & bit portions of the index are used to select the *
|
||||
* desired magnet. The added carry is used to make the *
|
||||
* effective addr even or odd in order to turn the magnet off *
|
||||
* or on. The EFFECTIVE addresses for all drive functions are *
|
||||
* shown below: *
|
||||
* MAG0FF = $C0s0 ;Turn stepper motor magnet 0 off. *
|
||||
* MAG0N = $C0s1 ;Turn stepper motor magnet 0 on. *
|
||||
* MAG1OFF = $C0s2 ;Turn stepper motor magnet 1 off. *
|
||||
* MAG1ON = $C0s3 ;Turn stepper motor magnet 1 on. *
|
||||
* MAG2OFF = $C0s4 ;Turn stepper motor magnet 2 off. *
|
||||
* MAG2ON = $C0s5 ;Turn stepper motor magnet 2 on. *
|
||||
* MAG3OFF = $C0s6 ;Turn stepper motor magnet 3 off. *
|
||||
* MAG3ON = $C0s7 ;Turn stepper motor magnet 3 on. *
|
||||
* MTR0FF = $C0s8 ;Wake up controller and spin disk. *
|
||||
* ;This switch must be thrown before a *
|
||||
* ;specific drive (1 or 2) is selected. *
|
||||
* MTR0N = $C0s9 ;Turn disk drive motor off. *
|
||||
* SELDRV1 = $C0sA ;Select drive number 1. *
|
||||
* SELDRV2 = $C0sB ;Select drive number 2. *
|
||||
* The following addresses are used to read or write data *
|
||||
* bytes or to check the status of the write protect switch. *
|
||||
* As shown below, they are always used in specific combinations *
|
||||
* to evoke a certain range of responses from the controller *
|
||||
* card. The firmware affected on the controller card is called *
|
||||
* a logic state sequencer. It is a nibble-based language that *
|
||||
* only contains six different instructions and is transparent to *
|
||||
* the monitor ROM disassembler. (See UNDERSTANDING THE APPLE II *
|
||||
* by Jim Sather for further explaination.) *
|
||||
* Q6L = $C0sC ;Shift byte in or out of data latch. *
|
||||
* Q6H = $C0sD ;Load latch from data bus. *
|
||||
* Q7L = $C0sE ;Prepare to read. *
|
||||
* Q7H = $C0sF ;Prepare to write. *
|
||||
* When used in combinations: *
|
||||
* Q7L plus Q6L = select read sequence and then read a byte. *
|
||||
* Q6H plus Q7L = check write protect switch and select write *
|
||||
* sequence. *
|
||||
* Q7H plus Q6H = select write sequence and load data register *
|
||||
* with output byte. *
|
||||
* Q6H plus Q6L = load latch from data bus and write byte. *
|
||||
* (Must have previously selected Q7H.) *
|
||||
* - Each disk drive contains two motors. One motor (usually *
|
||||
* referred to as the "drive motor") spins the disk at a *
|
||||
* constant speed. (When the drive motor is first turned on, a *
|
||||
* delay is used to wait for the drive to come up to speed *
|
||||
* before attempting to read or write disk bytes.) Another *
|
||||
* motor (called a "stepper motor") moves the read/write head *
|
||||
* across the disk to position the head at different track *
|
||||
* positions. *
|
||||
* - The stepper motor can be envisioned as containing a central *
|
||||
* magnet on a rotatable shaft and a circle of four fixed *
|
||||
* magnets (magnets 0 to 3) surrounding the shaft. Each time a *
|
||||
* peripheral magnet is enegized, the central shaft is rotated *
|
||||
* until its magnet is in line with the energized peripheral *
|
||||
* magnet. By turning the fixed peripheral magnets on and off *
|
||||
* in sequence, we can spin the shaft of the stepper motor. *
|
||||
* Movement of this shaft causes the read/write head to "step" *
|
||||
* across the disk. Each time the next magnet in sequence is *
|
||||
* turned on, the shaft is rotated one quarter turn. One *
|
||||
* quarter turn of the shaft moves the read/write head half a *
|
||||
* track width. *
|
||||
* - Normally, DOS only writes data at even magnet positions *
|
||||
* because the drive head does not have good enough resolution *
|
||||
* to distinguish information in adjacent half-track positions. *
|
||||
* The drive head is stepped to a higher track position as the *
|
||||
* magnets are turned on and off in ascending order. *
|
||||
* Similarly, a descending reference to the magnets causes *
|
||||
* movement to a lower track position. Each time a magnet is *
|
||||
* turned on or off, a delay is used to give the shaft magnet *
|
||||
* time to properly align with a peripheral magnet. The amount *
|
||||
* of delay used is inversely proportional to the acceleration *
|
||||
* of the motor. An example of the on/delay/off sequence used *
|
||||
* to step the head from track $02 to track $04 is shown below: *
|
||||
* 1on - delay - 0off - delay - 2on - delay - 1off - delay - *
|
||||
* 3on - delay - 2off - delay - 0on - delay - 3off - delay - *
|
||||
* 0off - delay. *
|
||||
* Similarly, moving the head from track $04 to track $02 *
|
||||
* requires the following sequence: *
|
||||
* 3on - delay - 0off - delay - 2on - delay - 3off - delay - *
|
||||
* 1on - delay - 2off - delay - 0on - delay - 1off - delay - *
|
||||
* 0off. *
|
||||
* Note that the last-energized magnet is always turned off. *
|
||||
* This is done as a safety measure because magnet-1-on is *
|
||||
* hard wired into the write protect switch. (The boot process *
|
||||
* is an exception to this rule. The controller ROM leaves *
|
||||
* magnet0 energized.) *
|
||||
* - Some protected programs modify DOS to skip entire tracks or *
|
||||
* write data at odd-numbered magnet positions. However, *
|
||||
* because the controller ROM always uses track $00 and because *
|
||||
* crosstalk occurs when data is less than one full track width *
|
||||
* apart, the data is actually written on a half-track disk at *
|
||||
* the following track positions: 0, 1+1/2, 2+1/2, 3+1/2, ..., *
|
||||
* 31+1/2, 32+1/2, 33+1/2. For instance, if you wanted to move *
|
||||
* the head from track $02 to track $04+1/2, you could add the *
|
||||
* following sequence to that described above: *
|
||||
* - delay - 1on - delay - 0off - 1 off -delay. *
|
||||
* - Data can even be written on quarter track positions (that *
|
||||
* is, tracks 0, 1+1/4, 2+1/4, ..., 31+1/4, 32+1/4, 33+1/4) by *
|
||||
* turning on two adjacent magnets almost simultaneously in *
|
||||
* order to position the head between the two magnets. For *
|
||||
* instance, if you wanted to move from track $02 to track *
|
||||
* $04+1/4, you could patch DOS to automatically add the *
|
||||
* following instructions to the normal sequence described *
|
||||
* above: - 1on - no delay - 0on - very short delay - 1off - *
|
||||
* no delay - 0off - delay. *
|
||||
* *
|
||||
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
||||
|
||||
|
||||
(B052)
|
||||
RWTSDRVR STX IBTRK ;Enter with (x) = trk wntd.
|
||||
STY IBSECT ; (y) = sector wntd.
|
||||
RWTSDRV1 STA IBCMD ; (a) = opcode for RWTS.
|
||||
(B058) ;RWTSDRV1 is the entry point used by the
|
||||
;Init function handler.
|
||||
(B05B) CMP #2 ;Is cmd a write?
|
||||
(B05D) BNE SKPWRSET ;No, so branch. Note: "CMP" conditions:
|
||||
;(c)=0 if seek ($00) or read ($01).
|
||||
;(c)=1 if write ($02) or format ($03).
|
||||
(B05F) ORA UPDATFLG ;Condition UPDATFLG to designate that
|
||||
(B062) STA UPDATFLG ;last operation was a write for next
|
||||
;time around.
|
||||
|
||||
* Finish setting up RWTS's
|
||||
* input/output block (IOB).
|
||||
(B065)
|
||||
SKPWRSET LDA VOLWA ;Put complimented vol in IOB.
|
||||
EOR #$FF
|
||||
STA IBVOL
|
||||
LDA SLOT16WA ;Put slot*16 in IOB.
|
||||
STA IBSLOT
|
||||
LDA DRVWA ;Put drive in IOB.
|
||||
STA IBDRVN
|
||||
LDA SECSIZWA ;Put sector length in IOB
|
||||
STA IBSECSZ ;(standard size of dec. 256
|
||||
LDA SECSIZWA+1 ;or hex $0100 bytes).
|
||||
STA IBSECSZ+1
|
||||
LDA #1 ;ALWAYS designate table type as 1.
|
||||
STA IBTYPE
|
||||
LDY ADRIOB ;Set (y) & (a) to point
|
||||
LDA ADRIOB+1 ;at RWTS's IOB.
|
||||
(B090) JSR ENTERWTS ;Go call RWTS.
|
||||
|
||||
* Route execution to RWTS.
|
||||
* (Normal entry route to RWTS for custom
|
||||
* assembly language programs. See preamble
|
||||
* for required entry conditions.)
|
||||
(B7B5)
|
||||
ENTERWTS PHP ;Save status reg (with conditioned carry) on stk.
|
||||
;(c) = 0 if doing seek ($00) or read ($01).
|
||||
;(c) = 1 if doing write ($02) or format ($03).
|
||||
(B7B6) SEI ;Set interrupt disable flag to prevent
|
||||
(B7B7) JSR RWTS ;any further maskable interrupts
|
||||
;when doing real-time programming.
|
||||
|
||||
* Read/Write Track/Sector (RWTS).
|
||||
* Enter with (y)/(a) pointing at
|
||||
* RWTS's input/output block (IOB).
|
||||
(BD00)
|
||||
RWTS STY PTR2IOB ;Set up a zero page
|
||||
STA PTR2IOB+1 ;pointer to RWTS's IOB.
|
||||
LDY #2 ;Initialize cntr for max of 2 recalibs.
|
||||
STY RECLBCNT
|
||||
LDY #4 ;Initialize cntr for # or re-seeks betwn recalibs.
|
||||
STY RSEEKCNT
|
||||
LDY #1 ;Get slot*16 from IOB & put it
|
||||
LDA (PTR2IOB),Y ;in (x) so can use it to index
|
||||
(BD12) TAX ;base addresses for drive functions.
|
||||
|
||||
* Check if wanted slot*16 = last slot*16.
|
||||
(BD13) LDY #15 ;Index to get val of last slot used.
|
||||
CMP (PTR2IOB),Y ;Compare wanted vs last.
|
||||
(BD17) BEQ SAMESLOT ;Take branch if using same slot.
|
||||
|
||||
* Want to use different slot so reset (x)
|
||||
* back to index old slot so can test old motor.
|
||||
(BD19) TXA ;Save slot*16 wanted on stk.
|
||||
PHA
|
||||
LDA (PTR2IOB),Y ;Get old slot*16 back and
|
||||
TAX ;stick it in (x) to index base addrs.
|
||||
PLA ;Get slot*16 wanted into (a) from stk
|
||||
PHA ;and keep it saved on stk.
|
||||
(BD20) STA (PTR2IOB),Y ;Update last-used slot*16 for next time.
|
||||
|
||||
* Check to see if last-used drive assoc with last-
|
||||
* used slot is still spinning. If it is, wait for
|
||||
* it to stop.
|
||||
(BD22) LDA Q7L,X ;Prep latch for input.
|
||||
CKSPIN LDY #8 ;Set cntr to insure at least 8 chks.
|
||||
LDA Q6L,X ;Strobe latch to read.
|
||||
CHKCHNG CMP Q6L,X ;Read again & cmp to last read.
|
||||
BNE CKSPIN ;Data changed, so still spinning.
|
||||
DEY ;No change, so chk with some
|
||||
(BD30) BNE CHKCHNG ;delays just to make sure.
|
||||
|
||||
* Get index for slot wanted.
|
||||
(BD32) PLA ;Get slot*16 back off stk
|
||||
(BD33) TAX ;and put it in (x).
|
||||
|
||||
* Chk to see if a drive assoc with slot wanted
|
||||
* is still spinning. (As soon as get a change then
|
||||
* know it's spinning. If no change, chk at least
|
||||
* 8 times to be certain it is off.)
|
||||
(BD34)
|
||||
SAMESLOT LDA Q7L,X ;Set read mode.
|
||||
LDA Q6L,X ;Strobe latch to read.
|
||||
LDY #8 ;Set cntr for 8 chks if needed.
|
||||
STRBAGN LDA Q6L,X ;Strobe latch again.
|
||||
PHA ;Delay 14 machine cycles.
|
||||
PLA
|
||||
PHA
|
||||
PLA
|
||||
STX SLOTPG5 ;Save slot*16 wntd in page 5.
|
||||
CMP Q6L,X ;Has data changed yet?
|
||||
BNE DONETEST ;Yes - data changed, so disk spinning.
|
||||
DEY ;No - no change, see if chkd enough times.
|
||||
BNE STRBAGN ;Chk at least 8 times.
|
||||
DONETEST PHP ;Save test results on stk so can later
|
||||
(BD4E) ;chk if need extra delay or not.
|
||||
|
||||
* Turn motor on in a drive assoc with slot wanted
|
||||
* (just in case it wasn't already spinning).
|
||||
* Note: This uses drive with same # as last
|
||||
* drive used. This may or may not be the
|
||||
* specific drive # we want. However, we must use
|
||||
* this instruction to send power via the controller.
|
||||
* Once this switch is thrown, we can later re-route
|
||||
* that power to whichever drive we want by throwing
|
||||
* another switch to select drive1 or drive2.
|
||||
(BD4F) LDA MTRON,X ;Turn motor on.
|
||||
|
||||
* Establish z-page pointers to device characteristic
|
||||
* table (DCT) and RWTS's I/O buffer (so can use z-page
|
||||
* indirect addressing modes).
|
||||
* IBDCTP ---> PTR2DCT (3C,3D)
|
||||
* IBBUFP ---> PTR2BUF (3E,3F)
|
||||
(BD52) LDY #6 ;Get ptrs from RWTS's IOB
|
||||
MOVPTRS LDA (PTR2IOB),Y ;and put them in z-page.
|
||||
(BD56) STA: PTR2DCT-6,Y ;(Note: ":" used to force
|
||||
;a 3-byte instruction.)
|
||||
(BD59) INY
|
||||
CPY #10 ;4 bytes to copy (6 to 9).
|
||||
(BD5C) BNE MOVPTRS
|
||||
|
||||
* Check drive status.
|
||||
(BD5E) LDY #3 ;Save hi byte of motor-on-time
|
||||
LDA (PTR2DCT),Y ;count in z-page.
|
||||
STA MTRTIME+1
|
||||
LDY #2 ;Get drive # wanted.
|
||||
LDA (PTR2IOB),Y
|
||||
LDY #16 ;Set (y) = index to last-used drive.
|
||||
CMP (PTR2IOB),Y ;Drv wanted vs drv last used.
|
||||
BEQ SAMEDRV
|
||||
(BD6E) STA (PTR2IOB),Y ;Designate drv wanted as old drv
|
||||
;for next time around.
|
||||
(BD70) PLP ;Get status back off stk.
|
||||
(BD71) LDY #0 ;Reset status (z-flag off) to signal that
|
||||
;SPECIFIC DRIVE # we want in SPECIFIC SLOT
|
||||
;wanted was not originally spinning.
|
||||
(BD73) PHP ;Push updated status back on stk.
|
||||
SAMEDRV ROR ;Put low bit of drv wanted in carry.
|
||||
BCC USEDRV2 ;Branch if want drive 2.
|
||||
LDA SELDRV1,X ;Route power to select drive 1.
|
||||
BCS USEDRV1 ;ALWAYS.
|
||||
USEDRV2 LDA SELDRV2,X ;Route power to select drive 2.
|
||||
USEDRV1 ROR DRVZPG ;Put sign bit for which drive
|
||||
(BD7F) ;using in z-page: neg = drive1.
|
||||
; pos = drive2.
|
||||
|
||||
* Chk to see if a specific drive wanted in
|
||||
* specific slot wanted was originally on or not.
|
||||
(BD81) PLP ;Get previous test result.
|
||||
PHP ;Put it back on stk for later use.
|
||||
(BD83) BNE WASON ;Orig drv in orig slot was on.
|
||||
|
||||
* Specific drive wanted in specific slot
|
||||
* wanted was ORIGINALLY OFF, so delay a
|
||||
* bit to avoid positioning head during
|
||||
* the period of heavy current flow that
|
||||
* occurs when motor is turned on. (That
|
||||
* is, give line/capacitor time to
|
||||
* bleed down cause motor on/off switch
|
||||
* requires more current than stepper motor.)
|
||||
*
|
||||
* (Amount of delay is not constant cause
|
||||
* it depends on what is in accum & we don't
|
||||
* know cause we were just accessing hardware.)
|
||||
(BD85) LDY #7
|
||||
WAIT4MTR JSR DELAY ;Stall.
|
||||
(BD87)
|
||||
|
||||
* Main delay routine in DOS.
|
||||
* (Amt of delay = 100 * (a) microsecs.)
|
||||
(BA00)
|
||||
DELAY LDX #17
|
||||
DLY1 DEX
|
||||
BNE DLY1
|
||||
INC MTRTIME
|
||||
BNE DLY2
|
||||
INC MTRTIME+1
|
||||
DLY2 SEC
|
||||
SBC #1
|
||||
BNE DELAY
|
||||
(BA10) RTS
|
||||
|
||||
(BD8A) DEY
|
||||
BNE WAIT4MTR ;Go stall some more.
|
||||
(BD8D) LDX SLOTPG5 ;Restore (x) = slot*16.
|
||||
(BD90)
|
||||
WASON LDY #4 ;Get trk wanted.
|
||||
LDA (PTR2IOB),Y
|
||||
(BD94) JSR SEEKTRK ;Go move arm to desired trk.
|
||||
|
||||
(BE5A)
|
||||
SEEKTRK PHA ;Save # of trk wntd on stk.
|
||||
LDY #1 ;Get drive type (1- or 2-phase)
|
||||
(BE5D) LDA (PTR2DCT),Y ;from DCT. (P.S. the "II" in the
|
||||
;"DISK II" logo stamped on Apple's
|
||||
;disk drive denotes a two-phase
|
||||
;stepper motor.)
|
||||
(BE5F) ROR ;Put low byte of drive type in carry.
|
||||
PLA ;Get trk# wanted back in (a).
|
||||
(BE61) BCC SEEKIT ;Not using standard DRIVEII, using a
|
||||
;one-phase drive instead, ther4 skip
|
||||
;doubling of trk # & use SEEKIT as part
|
||||
;of routine instead of a subroutine.
|
||||
|
||||
* Using a two-phase drive.
|
||||
(BE63) ASL ;Double trk # wanted to get
|
||||
;number of 1/2 trk wanted.
|
||||
(BE64) JSR SEEKIT ;Move disk arm to desired track.
|
||||
|
||||
(BE6B)
|
||||
SEEKIT .
|
||||
.
|
||||
.
|
||||
---------------------------------------------
|
||||
l * Routine/subroutine to move drive arm
|
||||
l * to a specific trk position.
|
||||
l * Used as a subroutine when using Apple's
|
||||
l * disk drive II. Note when SEEKIT is used as a
|
||||
l * subroutine, DESTRK, PRESTRK, TRK4DRV1, TRK4DRV2,
|
||||
l * STPSDONE and HOLDPRES are all expressed in half
|
||||
l * tracks:
|
||||
l * DESTRK = destination half-track position.
|
||||
l * PRESTRK = present half-track position.
|
||||
l * HOLDPRES = present half-track position.
|
||||
l * TRK4DRV1 = base addr (when indexed by slot*16) pts
|
||||
l * at the addr that contains the last half-
|
||||
l * track # that drive 1 was aligned on.
|
||||
l * TRK4DRV2 = base addr (when indexed by slot*16) pts
|
||||
l * at the addr that contains the last half-
|
||||
l * track # that drive 2 was aligned on.
|
||||
l * STPSDONE = number of half tracks moved so far.
|
||||
l * If not using a II-phase drive, change all
|
||||
l * comments that read "half tracks" to read
|
||||
l * "full tracks".
|
||||
l (BE6B)
|
||||
l SEEKIT STA DESTRK ;(a) = 2*trk # wanted.
|
||||
l ; = # of halftrk wanted.
|
||||
l (BE6D) JSR SLOTX2Y ;Set (y) = slot.
|
||||
l
|
||||
l * Convert slot*16 from
|
||||
l * (x) to slot in (y).
|
||||
l (BE8E)
|
||||
l SLOTX2Y TXA ;Get slot*16 from (x).
|
||||
l LSR ;Divide it by 16.
|
||||
l LSR
|
||||
l LSR
|
||||
l LSR
|
||||
l TAY ;Put slot # in (y).
|
||||
l (BE94) RTS
|
||||
l
|
||||
l (BE70) LDA TRK4DRV1,Y ;Pres halftrk# assoc with drv1.
|
||||
l (BE73) BIT DRVZPG ;Contains: neg = drive 1.
|
||||
l ; pos = drive 2.
|
||||
l (BE75) BMI SETPRSTK ;Branch if using drive 1.
|
||||
l LDA TRK4DRV2,Y ;Using drv 2 so get pres 1/2trk#.
|
||||
l SETPRSTK STA PRESTRK ;Save present halftrk#.
|
||||
l (BE7A)
|
||||
l
|
||||
l * Designate halftrk we are about to seek
|
||||
l * as present halftrk for next time around.
|
||||
l * (Put halftrk info in slot dependent locations.)
|
||||
l (BE7D) LDA DESTRK
|
||||
l BIT DRVZPG ;Chk to see which drive we are using.
|
||||
l BMI DRV1USG ;Branch if using drive 1.
|
||||
l STA TRK4DRV2,Y ;Using drv2 -store halftrk 4 next time.
|
||||
l BPL DRV2USG ;ALWAYS.
|
||||
l DRV1USG STA TRK4DRV1,Y ;Using drv1 -store halftrk 4 next time.
|
||||
l DRV2USG JMP SEEKABS
|
||||
l (BE8B) -----------
|
||||
l
|
||||
l * Move drive head to a given halftrk position.
|
||||
l * On entry: (x) = slot * 16.
|
||||
l * (a) = destination halftrack pos'n.
|
||||
l * PRESTRK = current halftrack pos'n.
|
||||
l (B9A0)
|
||||
l SEEKABS STX SLT16ZPG ;Save slot*16 in z-page.
|
||||
l STA DESTRK ;Save destin halftrk #.
|
||||
l CMP PRESTRK ;Dest halftrk = pres halftrk?
|
||||
l BEQ ARRIVED ;Yes - we are already there, so exit.
|
||||
l LDA #0 ;Init counter 4 # of halftrks moved.
|
||||
l (B9AB) STA STPSDONE
|
||||
l
|
||||
l * Save current halftrk pos'n & calc
|
||||
l * number of halftrks need to move minus 1.
|
||||
l (B9AD)
|
||||
l SAVCURTK LDA PRESTRK ;Save current halftrk pos'n.
|
||||
l STA HOLDPRES
|
||||
l SEC ;Calc (PRESTRK - DESTRK).
|
||||
l SBC DESTRK
|
||||
l BEQ ATDESTN ;At destin halftrk so go shutdown.
|
||||
l (B9B7) BCS MOVDWN ;Pres halftrk > destin halftrk so
|
||||
l ;want to move to lower trk.
|
||||
l
|
||||
l * Want to move to a higher halftrk #
|
||||
l * (PRESTRK - DESTRK = neg result).
|
||||
l
|
||||
l (B9B9) EOR #$FF ;Convert neg to pos.
|
||||
l (B9BB) INC PRESTRK ;Moving up, so inc current 1/2
|
||||
l ;trk pos'n for next time around.
|
||||
l (B9BE) BCC CKDLYNDX ;ALWAYS.
|
||||
l ------------
|
||||
l
|
||||
l * Want to move to lower halftrk #
|
||||
l * (PRESTRK - DESTRK = pos result).
|
||||
l (B9C0)
|
||||
l MOVDOWN ADC #$FE ;Simulate a subtract of 1. Actually
|
||||
l ;adding minus 1 (#$FF) cause carry
|
||||
l ;set. Want (a) to equal 1 less than
|
||||
l ;number of halftrks to move.
|
||||
l (B9C2) DEC PRESTRK ;Moving down so reduce pres 1/2
|
||||
l ;trk number for next time around.
|
||||
l
|
||||
l * Check to see which index to use to
|
||||
l * access the delay table. IF WE ARE
|
||||
l * WITHIN 12 STEPS of the destination
|
||||
l * or start positions, then use closest
|
||||
l * distance to start or end pos'n to
|
||||
l * index delay tables. Delay tables are
|
||||
l * only 12 bytes long, so if more than 12
|
||||
l * steps away from both start & destination,
|
||||
l * then use last index (y=12) to access table.
|
||||
l
|
||||
l * Check if closer to destination or start pos'n.
|
||||
l (B9C5)
|
||||
l CKDLYNDX CMP STPSDONE ;Compare # of halftrks moved
|
||||
l ;to # of halftrks need to move.
|
||||
l (B9C7) BCC CLSR2ND ;Branch if closer to destn than start posn.
|
||||
l
|
||||
l * Closer to start.
|
||||
l (B9C9) LDA STPSDONE ;Set (a) = dist from start pos'n.
|
||||
l CLSR2ND CMP #12 ;Are we within 12 steps of start
|
||||
l ;or destination pos'n?
|
||||
l (B9CD) BCS TURNON ;We are at or beyond 12 steps from
|
||||
l ;start or destn pos'n so use old
|
||||
l ;index to access delay table.
|
||||
l (B9CF)
|
||||
l PRESNDX TAY ;Use present distance to index delay table.
|
||||
l TURNON SEC ;Set carry so get odd index to base addr so
|
||||
l (B9D0) ;magnet will be turned ON.
|
||||
l (B9D1) JSR ONOROFF ;Turn magnet ON to suck stepper motor
|
||||
l ;to correct halftrack pos'n.
|
||||
l
|
||||
l (B9EE)
|
||||
l ONOROFF LDA PRESTRK ;Use lwr 2 bits of
|
||||
l ENTRYOFF AND #%00000011 ;1/2 trk pos'n to
|
||||
l ;index magnet.
|
||||
l (B9F3) ROL ;2*halftrack+(c).
|
||||
l ;If carry set,
|
||||
l ;result is odd &
|
||||
l ;magnet is energized.
|
||||
l (B9F4) ORA SLT16ZPG ;Merge index to magnet
|
||||
l ;with slot #.
|
||||
l (B9F6) TAX ;Use (x) for indexing.
|
||||
l (B9F7) LDA MAG0FF,X ;Use magnet0 off as
|
||||
l ;base address.
|
||||
l (B9FA) LDX SLT16ZPG ;Restore (x)=slot*16.
|
||||
l ARRIVED RTS
|
||||
l (B9FC)
|
||||
l
|
||||
l (B9D4) LDA ONTABLE,Y;Get time 2 leave magnet on from tbl.
|
||||
l (B9D7) JSR DELAY ;Delay to give drive time to act before
|
||||
l ;magnet is turned off again cause computer
|
||||
l ;too fast 4 peripheral & want smooth mov't.
|
||||
l
|
||||
l * Main delay routine in DOS.
|
||||
l * (Amt of delay = 100 * (a) microsecs.)
|
||||
l (BA00)
|
||||
l DELAY LDY #17
|
||||
l DLY1 DEX
|
||||
l BNE DLY1
|
||||
l INC MTRTIME
|
||||
l BNE DLY2
|
||||
l INC MTRTIME+1
|
||||
l DLY2 SEC
|
||||
l SBC #1
|
||||
l BNE DELAY
|
||||
l (BA10) RTS
|
||||
l
|
||||
l (B9DA) LDA HOLDPRES ;Get last halftrk pos'n in (a).
|
||||
l (B9DE) CLC ;Clr carry so index will come out even
|
||||
l ;and there4 magnet will be turned OFF.
|
||||
l (B9DD) JSR ENTRYOFF ;Turn magnet assoc with prev pos'n off.
|
||||
l
|
||||
l (B9F1)
|
||||
l ENTRYOFF AND #%00000011 ;Halftrk pos'n to
|
||||
l ;index magnet.
|
||||
l (B9F3) ROL ;2*halftrk+(c).
|
||||
l ;If carry set,
|
||||
l ;result is odd &
|
||||
l ;magnet is energized.
|
||||
l (B9F4) ORA SLT16ZPG ;Merge index to magnet
|
||||
l ;with slot #.
|
||||
l (B9F6) TAX ;Use (x) for indexing.
|
||||
l (B9F7) LDA MAG0FF,X ;Use magnet0 off as
|
||||
l ;base address.
|
||||
l (B9FA) LDX SLT16ZPG ;Restore (x)=slot*16.
|
||||
l ARRIVED RTS
|
||||
l (B9FC)
|
||||
l
|
||||
l (B9E0) LDA OFFTABLE,Y ;Get time 2 leave magnet off from table.
|
||||
l (B9E3) JSR DELAY ;Leave magnet off for a while to give
|
||||
l ;arm time to be properly aligned.
|
||||
l ;(Need time to suck it over & also to
|
||||
l ;decrease bounce or over-shoot.)
|
||||
l
|
||||
l * Main delay routine in DOS.
|
||||
l * (Amt of delay = 100 * (a) microsecs.)
|
||||
l (BA00)
|
||||
l DELAY LDY #17
|
||||
l DLY1 DEX
|
||||
l BNE DLY1
|
||||
l INC MTRTIME
|
||||
l BNE DLY2
|
||||
l INC MTRTIME+1
|
||||
l DLY2 SEC
|
||||
l SBC #1
|
||||
l BNE DELAY
|
||||
l (BA10) RTS
|
||||
l
|
||||
l (B9E6) INC STPSDONE
|
||||
l (B9E8) BNE SAVCURTK ;ALWAYS.
|
||||
l ------------
|
||||
l
|
||||
l * Arrived at destination halftrack.
|
||||
l (B9EA)
|
||||
l ATDESTN JSR DELAY ;Wait for peripheral again.
|
||||
l
|
||||
l * Main delay routine in DOS.
|
||||
l * (Amt of delay = 100 * (a) microsecs.)
|
||||
l (BA00)
|
||||
l DELAY LDY #17
|
||||
l DLY1 DEX
|
||||
l BNE DLY1
|
||||
l INC MTRTIME
|
||||
l BNE DLY2
|
||||
l INC MTRTIME+1
|
||||
l DLY2 SEC
|
||||
l SBC #1
|
||||
l BNE DELAY
|
||||
l (BA10) RTS
|
||||
l
|
||||
l * Turn last-used magnet off so exit with all
|
||||
l * phases (ie. magnets) off because MAG1ON is
|
||||
l * wired into the write-protect switch.
|
||||
l (B9ED) CLC ;Turn magnet OFF.
|
||||
l
|
||||
l * Turn magnet on or off.
|
||||
l (B9EE)
|
||||
l ONOROFF LDA PRESTRK ;Use halftrk pos'n 2 index magnet.
|
||||
l ENTRYOFF AND #%00000011 ;Only keep lwr 2 bits of halftrk#
|
||||
l (B9F2) ;because only 4 magnets (0,1,2 & 3).
|
||||
l (B9F3) ROL ;Multiply halftrk# * 2 and add (c)
|
||||
l ;If (c)=1, result even, magnet off
|
||||
l ;If (c)=0, result odd, magnet on
|
||||
l (B9F4) ORA SLT16ZPG ;Merge index to magnet with slot #
|
||||
l TAX ;Use (x) for indexing.
|
||||
l LDA MAG0FF,X ;Use magnet-0-off as base addr.
|
||||
l LDX SLT16ZPG ;Restore slot*16 in (x).
|
||||
l ARRIVED RTS
|
||||
l (B9FC)
|
||||
l--------------------------------------------
|
||||
.
|
||||
.
|
||||
.
|
||||
-----------------------
|
||||
l
|
||||
l
|
||||
(BE67) LSR PRESTRK ;Calc present whole trk #
|
||||
;(ie. pres halftrk# / 2).
|
||||
(BE6A) RTS
|
||||
|
||||
* Check to see if motor was originally on.
|
||||
(BD97) PLP ;Get prev motor test result off stack.
|
||||
BNE BEGINCMD ;Branch if motor was originally on.
|
||||
(BD9A) LDY MTRTIME+1 ;Motor wasn't originally on. However, we
|
||||
;have since turned in on. Now check if it
|
||||
;has been on long enough.
|
||||
(BD9C) BPL BEGINCMD ;Yes - no need to wait any longer.
|
||||
|
||||
* Although motor was turned on, it hasn't
|
||||
* been on long enough to do accurate
|
||||
* reading of bytes. There4, delay until
|
||||
* motor on time is 1 second (at which time
|
||||
* MTRTIME count is zero). (Part of time was
|
||||
* taken up to seek track.)
|
||||
(BD9E)
|
||||
TIME1 LDY #18
|
||||
TIME2 DEY
|
||||
BNE TIME2
|
||||
INC MTRTIME
|
||||
BNE TIME1
|
||||
INC MTRTIME+1
|
||||
(BDA9) BNE TIME1
|
||||
|
||||
* Motor is up to speed so now process command.
|
||||
* (Seek=00, Read=01, Write=02, Format=04.)
|
||||
* Counters:
|
||||
* READCNTR = allow up to 48 times to find correct
|
||||
* addr prologue between re-seeking.
|
||||
* RSEEKCNT = allow up to 4 re-seeks btwn recalibrations.
|
||||
* RECLBCNT = allow up to 2 recalibrations.
|
||||
* (There4, if necessary, allow up to 384
|
||||
* attempts to find correct prologue addr.)
|
||||
|
||||
* Begin RWTS command processing.
|
||||
(BDAB)
|
||||
BEGINCMD LDY #12 ;Get cmd from IOB.
|
||||
LDA (PTR2IOB),Y
|
||||
(BDAF) BEQ WASEEK ;Branch if cmd was "seek".
|
||||
----------
|
||||
|
||||
* Command was "SEEK" (null).
|
||||
(BE0B)
|
||||
WASEEK BEQ RWTSEXIT
|
||||
------------
|
||||
|
||||
* Signal success or failure & then shut down.
|
||||
* Note: Several references erroneously state that
|
||||
* the error code is zero if no error occurred.
|
||||
* However, a lone SEEK COMMAND ALWAYS SETS THE RETURN
|
||||
* CODE TO ZERO. Even if a read or write operation
|
||||
* is successful, the IOB error code will acquire a
|
||||
* random value (as a result of accessing a hardware
|
||||
* switch prior to entering this routine).
|
||||
|
||||
(BE46)
|
||||
RWTSEXIT CLC ;Clr carry to signal successful operation.
|
||||
HEX 24 ;"BIT $38" to skip "SEC" instruc below.
|
||||
RWTSERR SEC ;Set carry to signal unsuccessful operation.
|
||||
LDY #13 ;Store return code in IOB.
|
||||
STA (PTR2IOB),Y
|
||||
LDA MTROFF,X ;Turn motor off.
|
||||
(BE50) RTS
|
||||
|
||||
(B7BA) BCS ERRENTER ;Branch if operation unsuccessful.
|
||||
;(This branch is never taken with the seek command
|
||||
;because that operation doesn't contain any
|
||||
;facilities for error checking.)
|
||||
(B7BC) PLP ;Throw status off stk.
|
||||
CLC ;Signal successful.
|
||||
(B7BE) RTS
|
||||
============
|
||||
|
||||
(B093) LDA IBSMOD ;Get vol found from IOB
|
||||
STA VOLFM ;& put it in Fm parm list.
|
||||
LDA #$FF ;Designate vol wanted in
|
||||
(B09B) STA IBVOL ;IOB as 255 for next time.
|
||||
;(Actually using 0 cause FF EOR FF = 0.)
|
||||
(B09E) BCS ERRWTSDR ;Branch if UNsuccessful operation.
|
||||
;(Never taken when just doing a seek.)
|
||||
(B0A0) RTS
|
||||
============
|
1294
textfiles.com/apple/ANATOMY/rwts.s.txt
Normal file
1294
textfiles.com/apple/ANATOMY/rwts.s.txt
Normal file
File diff suppressed because it is too large
Load Diff
508
textfiles.com/apple/ANATOMY/rwtsd1.format.2.txt
Normal file
508
textfiles.com/apple/ANATOMY/rwtsd1.format.2.txt
Normal file
@@ -0,0 +1,508 @@
|
||||
|
||||
*-----------------------*
|
||||
* *
|
||||
* RWTSDRV1 USING FORMAT *
|
||||
* CONTinued *
|
||||
* *
|
||||
*-----------------------*
|
||||
.
|
||||
.
|
||||
.
|
||||
(BF1F) BCS VRFYRTN ;Irrelevant -already chkd write-protect
|
||||
;switch when we wrote the address.
|
||||
(BF21) INC FRMTSEC ;Increase sec #.
|
||||
LDA FRMTSEC
|
||||
CMP #$10 ;Done all 16 secs yet?
|
||||
(BF27) BCC FRMTASEC ;No - go do some more.
|
||||
|
||||
* VERIFY a single track.
|
||||
|
||||
* Note: We just finished formatting
|
||||
* sector $0F. Because sector $OF
|
||||
* shouldn't overwrite too much of the
|
||||
* sync gap (originally 128 syncs long)
|
||||
* that was written prior to sec $00, and
|
||||
* because we don't waste too much time
|
||||
* between writing the last byte of sec $0F
|
||||
* and looking for the next addr header, we
|
||||
* expect to begin our verification with
|
||||
* sec $00.
|
||||
|
||||
* Initialize counters.
|
||||
(BF29) LDY #$0F ;SET COUNTER FOR # OF SECS VERIFIED.
|
||||
STY FRMTSEC
|
||||
LDA #48 ;SET COUNTER FOR # OF ATTEMPTS.
|
||||
(BF2F) STA READCNTR
|
||||
|
||||
* Fill sector map with POSITIVE #'s.
|
||||
(BF32)
|
||||
FILSECMP STA SECFLGS,Y
|
||||
DEY
|
||||
(BF36) BPL FILSECMP
|
||||
|
||||
* Delay to let some syncs pass by.
|
||||
(BF38) LDY SYNCNTR ;Initialize (y).
|
||||
BYPSYNCS JSR VRFYRTN ;(12 cyc)
|
||||
JSR VRFYRTN ;(12 cyc)
|
||||
JSR VRFYRTN ;(12 cyc)
|
||||
PHA ;(3 cyc)
|
||||
PLA ;(4 cyc)
|
||||
NOP ;(2 cyc)
|
||||
DEY ;(2 cyc)
|
||||
(BF47) BNE BYPSYNCS ;(3 cyc on branch, 2 on fall thru)
|
||||
|
||||
* Read address of first sector encountered.
|
||||
* (THIS BETTER BE SECTOR 0!!!! If it isn't,
|
||||
* our drive is a bit too fast & we will
|
||||
* eventually have to reformat the track.)
|
||||
(BF49) JSR RDADDR ;Read addr of first sec encountered.
|
||||
;(See dis'mbly below.)
|
||||
(BF4C) BCS REREADDR ;Bad read, try again.
|
||||
LDA SECDSK ;Was sec read = sector 0?
|
||||
(BF50) BEQ RDNXTDAT ;Yes - go read next data sec.
|
||||
|
||||
* DIDN'T FIND SECTOR $00 WHEN EXPECTED.
|
||||
* Drive must be faster than anticipated
|
||||
* because sector $0F overlaid too much of
|
||||
* the long sync gap (gap 1) that was
|
||||
* originally written before sector $00.
|
||||
* We will have to reformat this track using
|
||||
* 128 self-syncs before sector $00 (gap 1)
|
||||
* and less sync bytes between other sectors
|
||||
* (gap 3). This will insure that less gap-1
|
||||
* syncs will be overwritten by sector $0F.
|
||||
* Note that, depending on just how much too
|
||||
* fast the drive is, we may have to reformat
|
||||
* this track several times before we get it
|
||||
* right. Each time we reformat, we reduce
|
||||
* the number of gap-3 syncs. If the sync
|
||||
* counter is greater than or equal to 16,
|
||||
* we write two less syncs. If the counter
|
||||
* is less than 16, we only reduce the gap-3
|
||||
* by one sync. In order to give the machine
|
||||
* time to decode information, we won't
|
||||
* allow a gap less than five syncs long.
|
||||
* (Note that we won't reformat the track
|
||||
* until we find the address header for sec $0F.
|
||||
* This presumably keeps like-numbered sectors
|
||||
* in adjacent tracks in some semblance of order.)
|
||||
(BF52) LDA #16
|
||||
CMP SYNCNTR ;Condition carry.
|
||||
LDA SYNCNTR ;If sync count < 16, subtract 1.
|
||||
SBC #1 ;Else subtract 2.
|
||||
STA SYNCNTR
|
||||
CMP #5 ;Do we have at least 5 syncs?
|
||||
BCS REREADDR ;Yes.
|
||||
SEC ;No - signal error cause need
|
||||
(BF61) RTS ;at least 5 syncs. Drive is
|
||||
============ ;so fast that it is out-to-lunch.
|
||||
|
||||
* Read the sector address.
|
||||
(BF62)
|
||||
RDNXTADR JSR RDADDR ;Read the address header.
|
||||
;(See dis'mbly below.)
|
||||
|
||||
(BF65) BCS BADREAD ;Branch if addr read was bad.
|
||||
|
||||
* Read the data proper.
|
||||
(BF67)
|
||||
RDNXTDAT JSR READATA ;Read the actual data bytes.
|
||||
(BF6A) BCC CKSECMAP ;Read was good so chk if this
|
||||
;sec has already been read.
|
||||
|
||||
(BF6C)
|
||||
BADREAD DEC READCNTR ;Either got a bad read or else we
|
||||
;already verified this sector.
|
||||
;Reduce the number of chances left.
|
||||
(BF6F) BNE RDNXTADR ;More chances left. Go try again.
|
||||
|
||||
* Doing a re-read. Will definitely
|
||||
* have to reformat.
|
||||
(BF71)
|
||||
REREADDR JSR RDADDR ;See dis'mbly below.
|
||||
(BF74) BCS NOTLAST ;Got a bad read.
|
||||
|
||||
* We will reformat but we don't want
|
||||
* to do so until we read sector $0F.
|
||||
* Have we found sector $0F yet?
|
||||
(BF76) LDA SECDSK ;Get phys # of sec just read.
|
||||
CMP #$0F ;Was it sector 15?
|
||||
BNE NOTLAST ;No, go look some more.
|
||||
(BF7C) JSR READATA ;Yes. Read the data in sec $0F.
|
||||
;(See dis'mbly below.)
|
||||
(BF7F) BCC FORMATRK ;Good read on sec 15 so now the timing
|
||||
(BF81) ;is right to GO REFORMAT THIS TRACK.
|
||||
NOTLAST DEC READCNTR ;Bad read, chk if more chances left.
|
||||
BNE REREADDR ;Yes - go try again.
|
||||
SEC ;Exhausted all chances, so set
|
||||
VRFYRTN RTS ;(c) as error flag & exit.
|
||||
(BF87) ============
|
||||
|
||||
* Check if this sector was previously
|
||||
* verified. If not, update sector
|
||||
* verification map. (If timing is
|
||||
* right, should never encounter an
|
||||
* already verified sec before FRMTSEC
|
||||
* decrements from $00 to $FF.)
|
||||
(BF88)
|
||||
CKSECMAP LDY SECDSK ;Use # of sec found as index
|
||||
;to the verification map.
|
||||
(BF8A) LDA SECFLGS,Y ;Get map byte (neg = prev verified).
|
||||
BMI BADREAD ;Oh Oh! Already verified this one.
|
||||
LDA #$FF ;Set byte in map to signal that
|
||||
STA SECFLGS,Y ;this sector was just verified.
|
||||
DEC FRMTSEC ;Any secs left to verify?
|
||||
(BF96) BPL RDNXTADR ;Yes - go do some more.
|
||||
|
||||
* All secs verified. Check if
|
||||
* we just did track $00.
|
||||
(BF98) LDA FRMTKCTR ;Was trk just formatted = trk $00?
|
||||
(BF9A) BNE NOTRK0 ;No - so exit cleanly.
|
||||
|
||||
* Just formatted & verified trk $00.
|
||||
* Trk $00 is the outside track and
|
||||
* therefore has the largest length
|
||||
* in which to write bytes. Because
|
||||
* subsequent tracks have a smaller
|
||||
* circumference, we must reduce the
|
||||
* number of syncs to write between
|
||||
* sectors (gap-3) so we can get all
|
||||
* the needed info into a smaller space.
|
||||
(BF9C) LDA SYNCNTR ;Check sync count.
|
||||
CMP #16 ;Less than 16 syncs?
|
||||
(BFA0) BCC VRFYRTN ;Yes - exit cleanly.
|
||||
;Don't want to start off with a
|
||||
;smaller gap, so skip the following
|
||||
;code which reduces the gap size.
|
||||
|
||||
* Reduce the size of gap-3.
|
||||
(BFA2) DEC SYNCNTR ;Gap > = 16 syncs long, so can afford to
|
||||
DEC SYNCNTR ;reduce it by two, so can accommodate
|
||||
NOTRK0 CLC ;a tighter track. Exit cleanly.
|
||||
(BFA7) RTS
|
||||
===========
|
||||
|
||||
(BEDC) LDA #8 ;Set (a) as default value in case
|
||||
;couldn't format.
|
||||
(BEDF) BCS ERRFRMT ;Branch if couldn't format.
|
||||
|
||||
* Do a read of trk just formatted.
|
||||
* (Eventhough track verified, read
|
||||
* it again until locate track 0.
|
||||
* Presumably, this (partially)
|
||||
* double checks verification and
|
||||
* keeps sectors in different tracks
|
||||
* somewhat adjacent?)
|
||||
(BEE0) LDA #48 ;Set 48 attempts to read.
|
||||
STA READCNTR
|
||||
RDAGAIN SEC ;Default (c)=1 to signal error.
|
||||
DEC READCNTR ;Reduce chances to read.
|
||||
BEQ ERRFRMT ;Exhausted all chances.
|
||||
(BEEB) JSR RDADDR ;Go read addr header to find sector
|
||||
;that we want to read or write.
|
||||
|
||||
* Read the address header.
|
||||
(B944)
|
||||
RDADDR LDY #$FC ;Designate 772 chances (#$FCFC to #$10000)
|
||||
;to find the correct address prologue.
|
||||
(B946) STY PROSCRTH
|
||||
KICKNTR INY
|
||||
BNE TRYD5
|
||||
INC PROSCRTH
|
||||
(B94D) BEQ ERRTN ;Error - can't find proglogue.
|
||||
|
||||
* Look for address prologue ("D5 AA 96").
|
||||
(B94F)
|
||||
TRYD5 LDA Q5L,X
|
||||
BPL TRYD5 ;Wait for a full byte.
|
||||
VERSUSD5 CMP #$D5 ;Was it a "D5"?
|
||||
BNE KICKNTR ;No - try again.
|
||||
NOP ;Wait 2 cycles.
|
||||
TRYAA LDA Q6L,X
|
||||
BPL TRYAA ;Wait for full byte.
|
||||
CMP #$AA ;Was it an "AA"?
|
||||
BNE VERSUSD5 ;No - retry sequence.
|
||||
(B962) LDY #3 ;Set (y) for later reading of
|
||||
;vol, trk, sec, checksum info
|
||||
;from address field.
|
||||
(B964)
|
||||
TRY96 LDA Q6L,X
|
||||
BPL TRY96 ;Wait for full byte.
|
||||
CMP #$96 ;Was it a "96"?
|
||||
(B96B) BNE VERSUSD5 ;No - retry sequence.
|
||||
|
||||
* Read odd-even encoded volume, track,
|
||||
* sector and checksum values from the
|
||||
* address field. (When reading,
|
||||
* calculate a running checksum.)
|
||||
* From: byte1: 1 b7 1 b5 1 b3 1 b1
|
||||
* byte2: b6 1 b4 1 b2 1 b0 1
|
||||
* -------------------------------
|
||||
* To: byte: b7 b6 b5 b4 b3 b2 b1 b0
|
||||
|
||||
(B96D) LDA #0 ;Initialize running checksum val.
|
||||
CALCK STA CKSUMCAL
|
||||
GETHDR LDA Q6L,X ;Get odd-encoded byte.
|
||||
BPL GETHDR ;Wait for a full byte.
|
||||
(B976) ROL ;Shift bits & put set
|
||||
;carry in bit0 pos'n.
|
||||
(B977) STA PROSCRTH ;Save shifted version.
|
||||
RDHDR LDA Q6L,X ;Get even-encoded byte.
|
||||
BPL GETHDR ;Wait for full byte.
|
||||
AND PROSCRTH ;Merge the bytes to normal.
|
||||
(B980) STA: CKSUMDSK,Y ;Store info read from addr
|
||||
;field in zero page:
|
||||
;$2F = vol found, $2E = trk found,
|
||||
;$2D = sec found, $2C = checksum found.
|
||||
;(Use ":" to force 3-byte instruction.)
|
||||
(B983) EOR CKSUMCAL ;Update running checksum.
|
||||
DEY
|
||||
BPL CALCK
|
||||
TAY ;Put checksum found in (y).
|
||||
(B989) BNE ERRTN ;If chec sum found < > 0, then error.
|
||||
;Hackers often change these two bytes
|
||||
;to "CLC" and "RTS" instructions in
|
||||
;order to defeat the address checksum
|
||||
;and ignore the address epilogue.
|
||||
|
||||
* Read first 2 bytes (only) of
|
||||
* the address epilogue ("DE AA").
|
||||
(B98B)
|
||||
TRYEPIDE LDA Q6L,X ;Get first byte.
|
||||
BPL TRYEPIDE ;Wait for a full byte.
|
||||
CMP #$DE ;Was it a "DE"?
|
||||
BNE ERRTN ;No - try again.
|
||||
NOP ;Stall 2 cycles.
|
||||
TRYEPIAA LDA Q6L,X ;Get second byte.
|
||||
BPL TRYEPIAA ;Wait for a full byte.
|
||||
CMP #$AA ;Was it an "AA"?
|
||||
BNE ERRTN ;No - retry sequence.
|
||||
GOODRTN CLC ;Signal good read.
|
||||
(B99F) RTS
|
||||
============
|
||||
|
||||
(B942)
|
||||
ERRTN SEC ;Signal bad read.
|
||||
(B943) RTS ;Hackers often change the "SEC" to
|
||||
============ ;a "CLC" in order to defeat error
|
||||
;checking.
|
||||
|
||||
(BEEE) BCS RDAGAIN ;Bad read - try again.
|
||||
LDA SECDSK ;Was it sector 0?
|
||||
BNE RDAGAIN ;No - try again.
|
||||
(BEF4) JSR READATA ;Last chance to read data.
|
||||
|
||||
* Read data sector into RWTS's buffers.
|
||||
* Look for data prologue.
|
||||
(B8DC)
|
||||
READATA LDY #32 ;Set (y) to designate 32
|
||||
REDUCEY DEY ;attempts to find data prologue.
|
||||
BEQ ERRTN ;Error - couldn't find data prologue.
|
||||
PRODATD5 LDA Q6L,X ;Get byte from data prologue.
|
||||
BPL PRODATD5 ;Wait for a full byte.
|
||||
VERSD5 EOR #$D5 ;Check if byte was a "D5".
|
||||
BNE REDUCEY ;Wasn't a "D5, reduce counter.
|
||||
NOP ;Stall 2 cycles.
|
||||
PRODATAA LDA Q6L,X ;Read next data prologue byte.
|
||||
BPL PRODATAA ;Wait for a full byte.
|
||||
CMP #$AA ;Was it an "AA"?
|
||||
BNE VERSD5 ;No - restart sequence.
|
||||
(B8F4) LDY #86 ;Set (y) for later use
|
||||
;in the read data routine.
|
||||
(B8F6)
|
||||
PRODATAD LDA Q6L,X ;Read next byte in data prologue.
|
||||
BPL PRODATAD ;Wait for a full byte.
|
||||
CMP #$AD ;Was it an "AD"?
|
||||
(B8FD) BNE VERSD5 ;No - restart search sequence.
|
||||
|
||||
* Read first 86 bytes of data into
|
||||
* RWTSBUF2 ($BC55 --> $BC00).
|
||||
*
|
||||
* Use disk byte as index to the
|
||||
* NDX2NIBL table which contains
|
||||
* offsets that we would be using
|
||||
* if we were accessing a table
|
||||
* of disk bytes when writing.
|
||||
* (That is, we are just doing
|
||||
* the opposite of writing.)
|
||||
* EOR value from NDX2NIBL table
|
||||
* with the previous EOR result.
|
||||
* (On entry, use #$00 for previous
|
||||
* EOR result.)
|
||||
(B8FF) LDA #0 ;Initialize (a) for later EORing.
|
||||
RDUCY DEY ;Reduce index to RWTSBUF2.
|
||||
STY PROSCRTH ;Save index.
|
||||
RDSKBYT LDY Q6L,X ;(y) = disk byte.
|
||||
BPL RDSKBYT ;Wait for a full byte.
|
||||
(B909) EOR NDX2NIBL-$96,Y ;Use (y) as index to tbl
|
||||
; of 2-encoded nibbles.
|
||||
(B90C) LDY PROSCRTH ;Store 2-encoded nibble in RWTSBUF2.
|
||||
STA RWTSBUF2,Y
|
||||
(B911) BNE RDUCY ;Conditioned from the "LDY PROSCRTH".
|
||||
|
||||
* Read rest of sector into RWTSBUF1
|
||||
* ($BB00 --> $BBFF).
|
||||
*
|
||||
* Use disk byte as index to the
|
||||
* NDX2NIBL table which contains
|
||||
* offsets that we would be using
|
||||
* if we were accessing a table
|
||||
* of disk bytes when writing.
|
||||
* (That is, we are just doing
|
||||
* the opposite of writing.)
|
||||
* EOR value from NDX2NIBL table
|
||||
* with the previous EOR result.
|
||||
(B913)
|
||||
SAVYNDX STY PROSCRTH ;Save index to RWTSBUF1.
|
||||
RDSKBYT2 LDY Q6L,X ;(y) = disk byte.
|
||||
BPL RDSKBYT2 ;Wait for a full byte.
|
||||
EOR NDX2NIBL-$96,Y ;Get 6-encoded nibble from tbl.
|
||||
LDY PROSCRTH ;Get index to RWTSBUF1.
|
||||
STA RWTSBUF1,Y ;Store 6-encoded nibble in RWTSBUF1.
|
||||
INY
|
||||
(B923) BNE SAVYNDX ;More disk bytes to read.
|
||||
|
||||
* Read the data checksum.
|
||||
(B925)
|
||||
RDCHECK LDY Q6L,X ;Get data checksum.
|
||||
BPL RDCHECK ;Wait for full byte.
|
||||
(B92A) CMP NDX2NIBL-$96,Y ;Converted checksum = val in $BBFF?
|
||||
;Remember: Val in $#BBFF is result of
|
||||
;previous cummulative EORing. There4,
|
||||
;this comparison with (a) detects any
|
||||
;(non-cancelling) error(s) that may
|
||||
;have occurred in the entire sector!!!
|
||||
(B92D) BNE ERRTN ;No - got an error.
|
||||
;Hackers often change these two bytes
|
||||
;to "CLC" and "RTS" instructions in
|
||||
;order to defeat the data checksum
|
||||
;and ignore the data epilogue.
|
||||
|
||||
* Read the first two bytes (only)
|
||||
* of the data epilogue ("DE AA").
|
||||
(B92F)
|
||||
EPIRDDE LDA Q6L,X ;Read first byte of data epilogue.
|
||||
BPL EPIRDDE ;Wait for a full byte.
|
||||
CMP #$DE ;Was it a "DE"?
|
||||
BNE ERRTN ;No - got an error.
|
||||
NOP ;Stall for 2 cycles.
|
||||
EPIRDAA LDA Q6L,X ;Read 2nd data epilogue byte.
|
||||
BPL EPIRDAA ;Wait for a full byte.
|
||||
CMP #$AA ;Was it an "AA"?
|
||||
BEQ GOODRTN ;Yes - got a good read.
|
||||
ERRTN SEC ;Signal bad read.
|
||||
(B943) RTS ;Hackers often change the "SEC" to a
|
||||
============ ;"CLC" in order to defeat error checking.
|
||||
|
||||
(B99E)
|
||||
GOODRTN CLC ;Signal good read.
|
||||
(B99F) RTS
|
||||
=============
|
||||
|
||||
(BEF7) BCS RDAGAIN ;Last chance bombed out!!!
|
||||
INC FRMTKCTR ;Kick up trk counter.
|
||||
LDA FRMTKCTR ;Set (a) for next trk count.
|
||||
CMP #$23 ;Done all trks yet (#0 to #34)?
|
||||
BCC FRMNXTRK ;No - GO FORMAT THE NEXT TRACK.
|
||||
CLC ;Signal finished all tracks.
|
||||
(BF02) BCC DONEFRMT ;ALWAYS - ONLY GOOD EXIT.
|
||||
------------
|
||||
|
||||
* Note: No matter what kind of error we
|
||||
* might have encountered when formatting,
|
||||
* the IOB error code is always set to $08.
|
||||
* This is later translated to an FM error
|
||||
* code (also $08) which DOS displays as
|
||||
* a I/O error message. (This is why trying
|
||||
* to format a write-protected disk results
|
||||
* in a an I/O error message instead of a
|
||||
* disk-write-protected message.)
|
||||
* If no error occurred, the IOB error byte
|
||||
* will be set to some random number (as a result of
|
||||
* referencing a hardware switch).
|
||||
(BF04)
|
||||
ERRFRMT LDY #13 ;Index to return code in IOB.
|
||||
STA (PTR2IOB),Y ;Store return code.
|
||||
SEC ;Signal that an error occurred.
|
||||
DONEFRMT LDA MTROFF,X ;Turn motor off & exit with (c)
|
||||
(BF0C) RTS ;denoting success status.
|
||||
============
|
||||
|
||||
(B7BA) BCS ERRENTER ;Branch if operation unsuccessful.
|
||||
PLP ;Throw status off stk.
|
||||
CLC ;Signal successful.
|
||||
(B7BE) RTS
|
||||
============
|
||||
|
||||
(B7BF)
|
||||
ERRENTER PLP ;Throw status off stk.
|
||||
SEC ;Signal UNsuccessful.
|
||||
(B7C1) RTS
|
||||
============
|
||||
|
||||
(B093) LDA IBSMOD ;Get vol found from IOB
|
||||
STA VOLFM ;& put it in Fm parm list.
|
||||
LDA #$FF ;Designate vol wanted in
|
||||
(B09B) STA IBVOL ;IOB as 255 for next time.
|
||||
;(Actually using 0 cause FF EOR FF = 0.)
|
||||
(B09E) BCS ERRWTSDR ;Branch if UNsuccessful operation.
|
||||
(B0A0) RTS
|
||||
=============
|
||||
|
||||
* Operation was NOT successful.
|
||||
(B0A1)
|
||||
ERRWTSDR LDA IBSTAT ;Get RWTS'S error code.
|
||||
|
||||
* Translate IOB error code (a) to
|
||||
* FM error code (y). (DOS later employs
|
||||
* the FM error code in the routine used
|
||||
* to print error messages.)
|
||||
(B0A4) LDY #7 ;Set (y) for FM vol mismatch.
|
||||
CMP #$20 ;Vol mismatch?
|
||||
BEQ SETFMERR ;Yes.
|
||||
LDY #$04 ;No.
|
||||
CMP #$10 ;Write protected?
|
||||
BEQ SETFMERR ;Yes.
|
||||
LDY #8 ;Must have been other, so
|
||||
SETFMERR TYA ;designate as general I/O error.
|
||||
(B0B3) JMP BADFMXIT ;Go handler error.
|
||||
------------
|
||||
|
||||
(B385)
|
||||
BADFMXIT SEC ;(c) = 1 to signal UNsuccessful.
|
||||
FMEXIT PHP ;Preserve success of operation on stk.
|
||||
STA RTNCODFM ;Put appropriate return code in FM parm list.
|
||||
LDA #0 ;Avoid that infamous $48 bug.
|
||||
STA STATUS
|
||||
(B38E) JSR CPYFMWA
|
||||
|
||||
(AE7E)
|
||||
CPYFMWA JSR SELWKBUF
|
||||
|
||||
* Point the A4L/H pointer at the DOS work buffer (chain).
|
||||
(AF08)
|
||||
SELWKBUF LDX #0 ;Designate work area buffer.
|
||||
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
||||
|
||||
(AF12)
|
||||
PT2FMBUF LDA WRKBUFFM,X ;Get addr of DOS's work buffer
|
||||
STA A4L ;(chain) from FM parm list and put
|
||||
LDA WRKBUFFM+1,X ;it in the A4L/H pointer.
|
||||
STA A4L+1
|
||||
(AF1C) RTS
|
||||
|
||||
* Copy work area buffer (non-chain)
|
||||
* to DOS work buffer (chain).
|
||||
(AE81) LDY #0
|
||||
STORWRK LDA FMWKAREA,Y
|
||||
STA (A4L),Y
|
||||
INY
|
||||
CPY #45
|
||||
BNE STORWRK
|
||||
(AE8D) RTS
|
||||
|
||||
(B391) PLP ;Exit with (c) conditioned accordingly.
|
||||
LDX STKSAV ;Reset the stack pointer so execution will
|
||||
TXS ;return to the caller of the function.
|
||||
(B396) RTS ;(Normally returns to AFTRFUNC ($A6AB)
|
||||
============ ;located in the FMDRIVER routine ($A6A8).)
|
1294
textfiles.com/apple/ANATOMY/rwtsdrvr.read.txt
Normal file
1294
textfiles.com/apple/ANATOMY/rwtsdrvr.read.txt
Normal file
File diff suppressed because it is too large
Load Diff
1328
textfiles.com/apple/ANATOMY/rwtsdrvr.write.txt
Normal file
1328
textfiles.com/apple/ANATOMY/rwtsdrvr.write.txt
Normal file
File diff suppressed because it is too large
Load Diff
2008
textfiles.com/apple/ANATOMY/symbol.cross.ref.txt
Normal file
2008
textfiles.com/apple/ANATOMY/symbol.cross.ref.txt
Normal file
File diff suppressed because it is too large
Load Diff
909
textfiles.com/apple/ANATOMY/t.dos.9d00.9f22.txt
Normal file
909
textfiles.com/apple/ANATOMY/t.dos.9d00.9f22.txt
Normal file
@@ -0,0 +1,909 @@
|
||||
**********************************
|
||||
* *
|
||||
* ADDRESSES REFERRED TO BY DOS *
|
||||
* *
|
||||
**********************************
|
||||
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* ZERO-PAGE ADDRESSES *
|
||||
*--------------------------------*
|
||||
|
||||
CH = $24 ;OFFSET FROM LEFT EDGE OF WINDOW
|
||||
;TO NEXT CHR POS'N ON SCRN LINE.
|
||||
;(RANGE: $00-$23.)
|
||||
PT2BTBUF = $26 ;PTR ($26,$27) TO TARGET BUF USED
|
||||
;WHEN READING IN DOS DURING BOOT.
|
||||
HOLDNIBL = $26 ;TEMP REG USED FOR HOLDING TWO-
|
||||
;ENCODED NIBBLES WHEN WRITING
|
||||
;A SECTOR DURING RWTS'S FORMAT OR
|
||||
;WRITE OPERATIONS.
|
||||
PROSCRTH = $26 ;TEMP REG USED FOR:
|
||||
;- DECODING ODD/EVEN ADDR FIELD
|
||||
; BYTES.
|
||||
;- CNTR AND INDEX TO RWTS BUFFERS
|
||||
; (1 & 2) WHEN POSTNIBBLING.
|
||||
;- CNTR FOR # OF CHANCES TO FIND
|
||||
; THE CORRECT ADDR PROLOGUE.
|
||||
STPSDONE = $26 ;- CNTR FOR # OF HALFTRKS MOVED.
|
||||
;- CURRENT DISTANCE (EXPRESSED IN
|
||||
; HALFTRACKS) FROM THE START OR
|
||||
; DESTINATION HALFTRACK POS'NS.
|
||||
FRMTSLOT = $27 ;SLOT * 16 USED TO INDEX DRIVE
|
||||
;BASE ADDRESSES.
|
||||
HOLDPRES = $27 ;HOLDS CURRENT HALFTRACK POSITION
|
||||
;WHEN SEEKING.
|
||||
CKSUMCAL = $27 ;RUNNING CHKSUM CALCULATION USED
|
||||
;WHEN READING ODD-EVEN ENCODED
|
||||
;ADDRESS FIELD BYTES.
|
||||
BASL = $28 ;PTR ($28,$29) TO THE LEFT END OF
|
||||
;THE SCREEN LINE.
|
||||
DESTRK = $2A ;DESTINATION HALFTRACK POS'N WHEN
|
||||
;SEEKING.
|
||||
SLT16ZPG = $2B ;SLOT*16 USED TO INDEX DRIVE
|
||||
;FUNCTIONS.
|
||||
CKSUMDSK = $2C ;DECODED CHECKUSM VAL READ FROM
|
||||
;ADDR FIELD (RWTS).
|
||||
SECDSK = $2D ;PHYS SEC # FOUND IN ADDR FIELD.
|
||||
TRKDSK = $2E ;TRK # FOUND IN ADDR FIELD.
|
||||
VOLDSK = $2F ;VOL # FOUND IN ADDR FIELD.
|
||||
PROMPT = $33 ;PROMPT CHAR USED TO SIGNAL INPUT
|
||||
;IS REQUIRED. ALSO USED AS A FLG
|
||||
;IN THE CMD PARSING & PROCESSING
|
||||
;ROUTINES.
|
||||
DRVZPG = $35 ;DENOTES DRIVE SELECTED:
|
||||
; NEG = DRIVE 1, POS = DRIVE 2.
|
||||
CSW = $36 ;MAIN OUTPUT HOOK (ALSO KNOWN AS
|
||||
;THE CHARACTER OUTPUT SWITCH).
|
||||
;PTR ($36,$37) TO DEVICE/ROUTINE
|
||||
;WHICH HANDLES OUTPUT CHARACTERS.
|
||||
KSW = $38 ;MAIN INPUT HOOK (ALSO KNOWN AS
|
||||
;THE KEYBOARD SWITCH).
|
||||
;PTR ($38,$39) TO DEVICE/ROUTINE
|
||||
;THAT HANDLES INPUT CHARACTERS.
|
||||
PTR2DCT = $3C ;PTR ($3C,$3D) TO RWTS'S DEVICE
|
||||
;CHARACTERISTIC TABLE.
|
||||
BOOTSEC = $3D ;PHYS SEC # WANTED WHEN BOOTING.
|
||||
PTR2RDSC = $3E ;PTR ($3E,$3F) TO BOOT0'S READ-
|
||||
;SECTOR SUBROUT'N (BTRDSEC, $CS5C
|
||||
;WHERE S=SLOT #, NORMALLY=$C65C.)
|
||||
PTR2BUF = $3E ;PTR ($3E,$EF) TO RWTS'S CURRENT
|
||||
;DATA BUFFER.
|
||||
HOLDAA = $3E ;- HOLDS A CONSTANT ($AA) FOR
|
||||
; PROLOGUE AND EPILOGUE BYTES
|
||||
; USED WHEN FORMATTING.
|
||||
;- ALSO USED AS A TEMP REG WHEN
|
||||
; CREATING ODD-EVEN ENCODED BYTS
|
||||
; ASSOC WITH THE ADDR FIELD.
|
||||
FRMTSEC = $3F ;HOLDS # OF SEC TO BE FORMATTED &
|
||||
;ALSO ACTS AS CNTR FOR # OF SECS
|
||||
;VERIFIED WHEN CHECKING TRK JUST
|
||||
;FORMATTED.
|
||||
A3L = $40 ;MULTIPURPOSE REG & PTR ($40,$41)
|
||||
FRMTVOL = $41 ;VOL # TO WRITE WHEN FORMATTING.
|
||||
A4L = $42 ;MULTIPURPOSE REG & PTR ($42,$43)
|
||||
A5L = $44 ;MULTIPURPOSE REG & PTR ($44,$45)
|
||||
FRMTKCTR = $44 ;TRK# TO WRITE/READ WHEN FORMAT-
|
||||
;TING/VERIFYING. ALSO ACTS AS A
|
||||
;CNTR OF THE # OF TRKS FORMATTED/
|
||||
;VERIFIED.
|
||||
SYNCNTR = $45 ;# OF SYNC BYTES 2 WRT BTWN SECS
|
||||
;& DELAY CNTR TO LET SOME SYNCS
|
||||
;PASS BY READ HEAD WHEN VERIFYING
|
||||
;A TRK JUST FORMATTED.
|
||||
MTRTIME = $46 ;MOTOR-ON-TIME COUNT ($46,$47).
|
||||
;CNTR USED TO DETERMINE IF THE
|
||||
;DRIVE MOTOR HAS BEEN ON LONG
|
||||
;ENOUGH TO DO RELIABLE READING.
|
||||
;THE MOTOR IS CONSIDERED TO BE UP
|
||||
;TO SPEED AFTER APPROX. 1 SECOND
|
||||
;(AT WHICH TIME, MTRTIME = 0000).
|
||||
PTR2IOB = $48 ;PTR ($48,49) TO RWTS'S INPUT/
|
||||
;OUTPUT BLOCK (IOB).
|
||||
STATUS = $48 ;STATUS REGISTER SAVE AREA.
|
||||
LOMEM = $4A ;PTR ($4A,$4B) 2 START OF INTEGER
|
||||
;BASIC'S VARIABLE TABLE.
|
||||
HIMEM = $4C ;PTR ($4C,$4D) TO END OF INTEGER
|
||||
;BASIC PRGM.
|
||||
TXTTAB = $67 ;PTR ($67,$68) TO START OF THE
|
||||
;APPLESOFT PRGM TEXT. DEFAULTS TO
|
||||
;$801 ON A COLDSTART (ONCE EXECU-
|
||||
;TION FLOWS INTO APPLESOFT).
|
||||
;PTR'S CONTENTS CAN BE CHANGED TO
|
||||
;ACCOMMODATE THE LOADING OF AN
|
||||
;APPLESOFT PRGM IN A NON-STANDARD
|
||||
;POSITION.
|
||||
VARTAB = $69 ;PTR ($69,$6A) TO START OF SIMPLE
|
||||
;VARIABLE TABLE.
|
||||
FRETOP = $6F ;PTR ($6F,$70) TO START OF FREE
|
||||
;SPACE (LOCATED BTWN THE END OF
|
||||
;THE VARIABLE TBL & THE START OF
|
||||
;THE STRING VALUES).
|
||||
MEMSIZ = $73 ;PTR ($73,$74) TO HIGHEST MEMORY
|
||||
;LOCATION (PLUS 1) THAT IS AVAIL-
|
||||
;ABLE TO AN APPLESOFT PRGM. (NOT
|
||||
;TO BE CONFUSED WITH THE END OF
|
||||
;THE APPLESOFT PRGM). CAN ALSO BE
|
||||
;EXPRESSED AS A PTR TO THE FIRST
|
||||
;BYTE OF THE DOS BUFFER REGION.
|
||||
CURLIN = $75 ;CURRENT APPLESOFT PROGRAM LINE
|
||||
;NUMBER ( $75,$76). USED BY DOS
|
||||
;2 DETERMINE IF BASIC IS RUNNING.
|
||||
;(CURLIN+1 CONTAINS AN $FF WHEN
|
||||
;COMPUTER IS IN THE IMMED MODE.)
|
||||
PRGEND = $AF ;PTR ($AF,$B0) 2 END OF APPLESOFT
|
||||
;PRGM (PLUS 1) IF FP CMD WAS USED
|
||||
;OR TO END OF PRGM (PLUS 2) IF A
|
||||
;NEW CMD WAS USED.
|
||||
INTPGMST = $CA ;PTR ($CA,$CB) TO START OF THE
|
||||
;INTEGER PRGM.
|
||||
INTVRLND = $CC ;INTEGER BASIC'S CURRENT END-OF-
|
||||
;VARIABLE PTR ($CC,$CD).
|
||||
PROTFLG = $D6 ;PRGM PROTECTION FLAG.
|
||||
;IF PROTECTION FLAG IS ON (NEG),
|
||||
;ALL APPLESOFT CMDS CAUSE A RUN &
|
||||
;DOS'S SAVE CMD CAUSE A PHONY
|
||||
;PROGRAM-TOO-LARGE ERROR MSG 2 BE
|
||||
;GENERATED.
|
||||
ERRFLG = $D8 ;ON-ERROR FLAG. EQUALS $80 IF
|
||||
;ON-ERR IS ACTIVE.
|
||||
RUNMODE = $D9 ;INTEGER BASIC'S MODE FLAG.
|
||||
;CONTAINS A NEG VALUE IF INTEGER
|
||||
;IS IN THE DEFERRED MODE.
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* PAGES TWO TO EIGHT *
|
||||
*--------------------------------*
|
||||
|
||||
BUF200 = $200 ;THE INPUT BUFFER ($200-$2FF).
|
||||
;(ALSO KNOWN AS KEYBOARD BUFFER.)
|
||||
|
||||
PG3DOSVT = $3D0 ;START OF PAGE-3 DOS VECTOR TBL.
|
||||
RESETVEC = $3F2 ;RESET VECTOR. CONTAINS ADDR OF
|
||||
;ROUT'N WHERE EXECUT'N DIVERTS TO
|
||||
;WHEN THE RESET KEY IS PRESSED.
|
||||
VLDBYTE = $3F4 ;RESET VALIDATION BYTE.
|
||||
;IF $3F3 EOR #$A5 IS NOT EQUAL TO
|
||||
;$3F4, THEN DISK REBOOTS AND A
|
||||
;COLDSTART IS DONE. OTHERWISE,
|
||||
;EXECUTION GOES TO THE ADDR IN
|
||||
;$3F2/$3F3.
|
||||
|
||||
TRK4DRV1 = $478 ;BASE ADR USED TO REFERENCE THE
|
||||
;LOCATION THAT CONTAINS THE LAST
|
||||
;HALFTRACK ON WHICH DRIVE 1 WAS
|
||||
;ALIGNED.
|
||||
PRESTRK = $478 ;- CURRENT HALFTRACK NUMBER.
|
||||
;- SAVE REG FOR WHOLE TRK# WANTED
|
||||
; WHEN HAVE TO GO RECALIBRATE.
|
||||
TRK4DRV2 = $4F8 ;BASE ADR USED TO REFERENCE THE
|
||||
;LOCATION THAT CONTAINS THE LAST
|
||||
;HALFTRACK ON WHICH DRIVE 2 WAS
|
||||
;ALIGNED.
|
||||
RSEEKCNT = $4F8 ;CNTR FOR # OF RE-SEEKS ALLOWED
|
||||
;BETWEEN RECALIBRATIONS (4 --> 1,
|
||||
;DO RECALIBRATION WHEN CNTR = 0.)
|
||||
|
||||
READCNTR = $578 ;CNTR FOR # OF ATTEMPTS ALLOWED 2
|
||||
;GET A GOOD ADDR OR DATA READ.
|
||||
SLOTPG5 = $5F8 ;SLOT*16 USED WHEN DOS WAS BOOTED
|
||||
|
||||
SLOTPG6 = $678 ;SLOT*16 USED WHEN FORMATTING &
|
||||
;WRITING.
|
||||
RECLBCNT = $6F8 ;CNTR FOR # OF RECALIBRATIONS
|
||||
;ALLOWED BEFORE RWTS GIVES UP.
|
||||
|
||||
BT1LDADR = $8FD ;BOOT1 LOAD ADDRESS ($8FD,$8FE).
|
||||
;VARIES FROM $B600 TO $BF00.
|
||||
;EVENTUALLY POINTS 2 THE START OF
|
||||
;BOOT2 ($B700).
|
||||
BT1PG2RD = $8FF ;INITIALLY CONTAINS # OF SECS TO
|
||||
;READ IN WHEN EXECUTING BOOT1.
|
||||
;ALSO DOUBLES AS LOGICAL SEC #.
|
||||
;(VARIES FROM $09 --> $00 -->$FF)
|
||||
;(SEE DISCUSSION IN FORMATTED
|
||||
;DIS'MBLY "THE BOOT PROCESS".)
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* RAM-BASED APPLESOFT ADDRESSES *
|
||||
* A(RAM) *
|
||||
*--------------------------------*
|
||||
CLRFPRAM = $E65 ;ENTRY POINT TO CLEAR VARIABLES
|
||||
;FROM A RAM-BASED APPLESOFT PRGM.
|
||||
RUNFPRAM = $FD4 ;ENTRY POINT 2 EXECUTE RAM-BASED
|
||||
;APPLESOFT PRGM.
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* DOS BUFFER START *
|
||||
*--------------------------------*
|
||||
|
||||
DOSNMBF1 = $9CD3 ;ADDR OF FIRST DOS NAME BUFFER.
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* DRIVE FUNCTION BASE ADDRS *
|
||||
*--------------------------------*
|
||||
* NOTE: THE ACTUAL ADDRESSES *
|
||||
* USED ARE DEPENDENT UPON WHICH *
|
||||
* SLOT HOUSES THE DSK CONTROLLER *
|
||||
* CARD. (SEE COMMENTS IN ANY ONE *
|
||||
* OF THE FORMATTED DISASSEMBLIES *
|
||||
* OF RWTS FOR MORE DETAILS.) *
|
||||
|
||||
MAG0FF = $C080 ;BASE ADDR TO TURN STEPPER MOTOR
|
||||
;MAGNET ON OR OFF.
|
||||
MTROFF = $C088 ;BASE ADDR TO TURN DRV MOTOR OFF.
|
||||
MTRON = $C089 ;BASE ADR TO TURN DRV MOTOR ON.
|
||||
SELDRV1 = $C08A ;BASE ADR TO SELECT DRIVE 1.
|
||||
SELDRV2 = $C08B ;BASE ADR TO SELECT DRIVE 2.
|
||||
Q6L = $C08C ;SHIFT BYTE IN OR OUT OF LATCH.
|
||||
Q6H = $C08D ;LOAD LATCH FROM DATA BUS.
|
||||
Q7L = $C08E ;PREPARE TO READ.
|
||||
Q7H = $C08F ;PREPARE TO WRITE.
|
||||
|
||||
BTRDSEC = $C65C ;BOOT0'S READ SECTOR SUBROUTINE.
|
||||
;(ACTUALLY=$CS5C, WHERE S=SLOT#.)
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* APPLESOFT ADDRESSES *
|
||||
*--------------------------------*
|
||||
RESTART = $D43C ;APLSFT BASIC'S WRMSTART ROUTINE.
|
||||
SETLINKS = $D4F2 ;ROUT'N THAT CLEARS ALL VAR'BLES,
|
||||
;RESETS THE STK PTR & RECALCS THE
|
||||
;LINKS IN @ APPLESOFT PRGM LINE.
|
||||
;(THIS ROUTINE IS WHAT ENABLES
|
||||
;APLSFT PRGMS TO BE RELOCATABLE.)
|
||||
SETZPTRS = $D665 ;APPLESOFT ROUTINE THAT SIMULATES
|
||||
;CLEAR & RESTORE STATEMENTS.
|
||||
NEWSTT = $D7D2 ;ROUTINE TO COLLECT & EXECUTE THE
|
||||
;APPLESOFT PRGM STATEMENT.
|
||||
BSCERHLR = $D865 ;BASIC'S ERROR-HANDLING ROUTINE.
|
||||
BASICCLD = $E000 ;BASIC'S COLDSTART ROUTINE.
|
||||
|
||||
|
||||
*--------------------------------*
|
||||
* MONITOR ROM ROUTINES *
|
||||
*--------------------------------*
|
||||
OLDBRK = $FA59 ;DEFAULT BREAK INTERRUPT HANDLER.
|
||||
INIT = $FB2F ;SCREEN INITIALIZATION ROUTINE.
|
||||
;(SET FULL SCREEN TEXT.)
|
||||
HOME = $FC58 ;BLANK OUT CURRENT SCROLL WINDOW
|
||||
;& PUT THE CURSOR IN THE TOP LEFT
|
||||
;CORNER OF THE WINDOW. (DOES NOT
|
||||
;RESET THE WINDOW SIZE.)
|
||||
RDKEY = $FD0C ;REQUEST INPUT VIA INPUT HOOK.
|
||||
KEYIN = $FD1B ;WAIT FOR INPUT FROM KEYBOARD.
|
||||
PRBYTE = $FDDA ;PRINT CONTENTS OF (A) AS HX VAL.
|
||||
COUT = $FDED ;ROUTE OUTPUT VIA THE OUTPUT HK.
|
||||
COUT1 = $FDF0 ;MONITOR ROM (TRUE) OUTPUT HNDLR.
|
||||
SETKBD = $FE89 ;SELECT KEYBOARD AS INPUT DEVICE.
|
||||
INPORT = $FE8B ;ENTRY POINT TO SELECT INPUT
|
||||
;DEVICE OTHER THAN KEYBOARD.
|
||||
SETVID = $FE93 ;SELECT SCREEN AS OUTPUT DEVICE.
|
||||
OUTPORT = $FE95 ;ENTRY POINT TO SELECT OUTPUT
|
||||
;DEVICE OTHER THAN SCREEN.
|
||||
MONRTS = $FF58 ;AN RTS INSTRUC LOC'D IN MONITOR
|
||||
;ROM. MANY RELOCATABLE PGMS "JSR"
|
||||
;TO HERE IN ORDER TO LOAD UP THE
|
||||
;STACK WITH THE ADDR OF THE "JSR"
|
||||
;SO THEY CAN FIND OUT THE PRGM'S
|
||||
;PRESENT LOCATION.
|
||||
MON = $FF65 ;NORM ENTRY ROUTE 2 MONITOR ROM.
|
||||
;("CALL -151" GOES HERE.)
|
||||
|
||||
|
||||
* ====================================
|
||||
* RELOCATABLE ADDRESS CONSTANTS TABLE.
|
||||
* ($9D00 - $9D0F)
|
||||
* (ADRS CAN BE CHANGED TO POINT TO
|
||||
* CUSTOMIZED ROUTINES, TABLES, ETC.)
|
||||
* ====================================
|
||||
|
||||
ADOSFNB1 DA DOSNMBF1 ;PTS TO FIRST DOS BUFFER AT ITS
|
||||
;FILE NAME FIELD.
|
||||
ADINPTCP DA INPTINCP ;PTS TO DOS'S INPUT INTERCEPT
|
||||
;ROUTINE.
|
||||
ADOPUTCP DA OPUTINCP ;PTS TO DOS'S OUTPUT INTERCEPT
|
||||
;ROUTINE.
|
||||
ADRPFNBF DA PRIMFNBF ;PTS TO PRIMARY FILENAME BUFFER.
|
||||
ADRSFNBF DA SCNDFNBF ;PTS TO SECONDARY FILENAME BUFFER.
|
||||
ADLENADR DA LENADRBF ;PTS TO 2-BYTE BUF THAT RECEIVES
|
||||
;BLOAD ADR & LENGTH READ FROM DSK
|
||||
ADOSTART DA ADOSFNB1 ;PTS TO 1RST BYTE OF DOS.
|
||||
ADFMPARM DA OPCODEFM ;PTS TO FM PARAMETER LIST.
|
||||
|
||||
|
||||
*=====================================
|
||||
* TABLE OF OUTPUT HANDLER ENTRY POINTS
|
||||
* ($9D10 - $9D1D)
|
||||
* (ADR-1 OF ROUT'NS WHICH HANDLE PRINT
|
||||
* STATEMENTS CONTAINING DOS CMDS.)
|
||||
*=====================================
|
||||
|
||||
OUTHNDTB DA OPUTHDL0-1 ;EVALUATE START OF INPUT LINE.
|
||||
DA OPUTHDL1-1 ;COLLECT THE DOS COMMAND.
|
||||
DA OPUTHDL2-1 ;PRINT A <CR> AND RETURN.
|
||||
DA OPUTHDL3-1 ;PROCESS THE INPUT INFORMATION.
|
||||
DA OPUTHDL4-1 ;WRITE DATA TO DISK.
|
||||
DA OPUTHDL5-1 ;ANALYZE 1RST CHR OF DATA FRM DSK
|
||||
DA OPUTHDL6-1 ;IGNORE INPUT PROMPT ("?").
|
||||
|
||||
|
||||
*=======================================
|
||||
* COMMAND HANDLER ENTRY POINT TABLE
|
||||
* ($9D1E - $9D55)
|
||||
* ALL ADRS ARE ONE LESS THAN THE ACTUAL
|
||||
* ENTRY POINTS BECAUSE THESE ROUT'NS ARE
|
||||
* ENTERED VIA A "STACK JUMP". IF YOU
|
||||
* CREATE A NEW DOS CMD, PLACE THE ADR-1
|
||||
* OF THE NEW CMD IN THE FOLLOWING TABLE.
|
||||
* (ALSO MAKE SURE THAT THE FIRST CMD IN
|
||||
* THE TABLE CAN CREATE A NEW FILE.)
|
||||
* SOME AUTHORS DISABLE SPECIFIC DOS
|
||||
* CMDS BY POINTING THE CMD'S TABLE ADR
|
||||
* AT DOS'S COLDSTART ROUTINE OR BY
|
||||
* PLACING AN "RTS" OPCODE AT THE CMD'S
|
||||
* ENTRY POINT.
|
||||
*=======================================
|
||||
|
||||
CMDTBL DA CMDINIT-1 ; $A54F-1
|
||||
DA CMDLOAD-1 ; $A413-1
|
||||
DA CMDSAVE-1 ; $A397-1
|
||||
DA CMDRUN-1 ; $A4D1-1
|
||||
DA CMDCHAIN-1 ; $A4F0-1
|
||||
DA CMDELETE-1 ; $A263-1
|
||||
DA CMDLOCK-1 ; $A271-1
|
||||
DA CMDUNLOK-1 ; $A275-1
|
||||
DA CMDCLOSE-1 ; $A2EA-1
|
||||
DA CMDREAD-1 ; $A51B-1
|
||||
DA CMDEXEC-1 ; $A5C6-1
|
||||
DA CMDWRITE-1 ; $A510-1
|
||||
DA CMDPOSN-1 ; $A5DD-1
|
||||
DA CMDOPEN-1 ; $A2A3-1
|
||||
DA CMDAPPND-1 ; $A298-1
|
||||
DA CMDRENAM-1 ; $A281-1
|
||||
DA CMDCATLG-1 ; $A56E-1
|
||||
DA CMDMON-1 ; $A233-1
|
||||
DA CMDNOMON-1 ; $A23D-1
|
||||
DA CMDPR-1 ; $A229-1
|
||||
DA CMDIN-1 ; $A22E-1
|
||||
DA CMDMXFIL-1 ; $A251-1
|
||||
DA CMDFP-1 ; $A57A-1
|
||||
DA CMDINT-1 ; $A59E-1
|
||||
DA CMDBSAVE-1 ; $A331-1
|
||||
DA CMDBLOAD-1 ; $A35D-1
|
||||
DA CMDBRUN-1 ; $A38E-1
|
||||
DA CMDVERFY-1 ; $A27D-1
|
||||
|
||||
|
||||
*===========================================
|
||||
* ACTIVE BASIC ENTRY POINT VECTOR TABLE
|
||||
* ($9D56 - $9D61)
|
||||
* (NOTE: TBL CUTOMIZED BY DOS ACCORDING TO
|
||||
* THE CURRENT VERSION OF BASIC THAT IS BEING
|
||||
* USED. ADRS SHOWN AS OPERANDS BELOW,
|
||||
* ASSUME THAT APPLESOFT BASIC IS ACTIVE.)
|
||||
*===========================================
|
||||
|
||||
CHAINTRY DA RUNFPROM ;ADR OF CHAIN ENTRY PT TO BASIC.
|
||||
RUNTRY DA RUNFPROM ;ADR OF BASIC'S RUN CMD.
|
||||
ADBSCERR DA BSCERHLR ;ADR OF BASIC'S ERROR HANDLER.
|
||||
TOCLDVEC DA BASICCLD ;ADR OF BASIC'S COLD START ROUT'N
|
||||
TOWRMVEC DA RESTART ;ADR OF BASIC'S WARM START ROUT'N
|
||||
RLOCNTRY DA SETLINKS ;ADR OF ROUT'N THAT ENABLES BASIC
|
||||
;PRGMS TO BE RELOCATABLE.
|
||||
|
||||
|
||||
*====================================
|
||||
* IMAGE OF INTEGER BASIC'S ENTRY
|
||||
* POINT VECTOR TABLE ($9D62 - $9D6B).
|
||||
*====================================
|
||||
|
||||
IMGINTV DA $E836
|
||||
DA $A4E5
|
||||
DA $E3E3
|
||||
DA $E000
|
||||
DA $E003
|
||||
|
||||
|
||||
*=======================================
|
||||
* IMAGE OF ROM APPLESOFT BASIC'S ENTRY
|
||||
* POINT VECTOR TABLE ($9D6C - $9D77).
|
||||
*=======================================
|
||||
|
||||
IMGFPV DA RUNFPROM
|
||||
DA RUNFPROM
|
||||
DA BSCERHLR
|
||||
DA BASICCLD
|
||||
DA RESTART
|
||||
DA SETLINKS
|
||||
|
||||
|
||||
*========================================
|
||||
* IMAGE OF RAM APPLESOFT BASIC'S ENTRY
|
||||
* POINT VECTOR TABLE ($9D78 - $9D83).
|
||||
* (NOTE: A(RAM) REFERS TO A DISK-BASED
|
||||
* VERSION OF APPLESOFT BASIC THAT IS
|
||||
* HOUSED ON THE "SYSTEMS MASTER" DISK.)
|
||||
*========================================
|
||||
|
||||
IMGARAMV DA FPRAMRUN
|
||||
DA FPRAMRUN
|
||||
DA $1067
|
||||
DA $9D84
|
||||
DA $C3C
|
||||
DA $CF2
|
||||
|
||||
|
||||
*=================================
|
||||
* DOS'S COLD START ROUTINE.
|
||||
* (PS. DON'T CONFUSE WITH BASIC'S
|
||||
* COLD START ROUTINE - BASICCLD.)
|
||||
*=================================
|
||||
|
||||
* GET SLOT & DRV #'S & STORE THEM AS
|
||||
* DEFAULT VALS IN CASE NO SUCH PARMS
|
||||
* WERE ISSUED WITH THE COMMAND.
|
||||
|
||||
DOSCOLD LDA IBSLOT ;SLOT# * 16 FROM RWTS'S IOB TBL.
|
||||
LSR ;DIVIDE BY 16.
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
STA SLOTPRSD ;PUT SLOT IN PARSED TABLE.
|
||||
LDA IBDRVN ;DRV # FROM RWTS'S IOB.
|
||||
STA DRVPRSD ;PUT DRIVE # IN PARSED TABLE.
|
||||
|
||||
* CHK WHICH BASIC IS IN ROM.
|
||||
|
||||
LDA BASICCLD ;SET IDENTIFYING BYTE WITH
|
||||
EOR #$20 ;$20 = INTEGER OR $40 = A(ROM).
|
||||
BNE ISFPROM ;BRANCH IF APPLESOFT IS IN ROM.
|
||||
|
||||
* INTEGER BASIC IS ACTIVE.
|
||||
|
||||
ISINT STA ACTBSFLG ;SET ACTIVE BASIC FLAG
|
||||
;TO DENOTE INTEGER (#$00).
|
||||
|
||||
* COPY IMAGE OF INTEGER BASIC'S
|
||||
* ENTRY POINT VECTOR TABLE TO THE
|
||||
* ACTIVE BASIC ENTRY VECTOR TABLE.
|
||||
|
||||
LDX #10
|
||||
INT2BSIC LDA IMGINTV-1,X
|
||||
STA CHAINTRY-1,X
|
||||
DEX
|
||||
BNE INT2BSIC ;10 BYTES TO COPY (10 --> 1).
|
||||
JMP BYPASWRM
|
||||
|
||||
* COPY IMAGE OF APPLESOFT'S ENTRY
|
||||
* POINT VECTOR TABLE TO THE ACTIVE
|
||||
* BASIC ENTRY POINT VECTOR TABLE.
|
||||
|
||||
ISFPROM LDA #$40 ;SET ACTIVE BASIC FLAG TO #$40
|
||||
STA ACTBSFLG ;SO SIGNAL APPLESOFT ROM.
|
||||
LDX #12
|
||||
AROM2BSC LDA IMGFPV-1,X
|
||||
STA CHAINTRY-1,X
|
||||
DEX
|
||||
BNE AROM2BSC
|
||||
BYPASWRM SEC ;(C) = 1, SIGNAL FOR COLDSTART.
|
||||
;(C) = 0, SIGNAL FOR WARMSTART.
|
||||
BCS CMWRMCLD ;FORCE BRANCH TO BYPASS PART OF
|
||||
;THE WARMSTART ROUTINE.
|
||||
|
||||
|
||||
*=================================
|
||||
* DOS'S WARMSTART ROUTINE.
|
||||
* (PS. DON'T CONFUSE WITH BASIC'S
|
||||
* WARMSTART ROUTINE - RESTART.)
|
||||
*=================================
|
||||
|
||||
DOSWARM LDA ACTBSFLG ;SEE WHICH LANGUAGE IS UP.
|
||||
BNE CKBASIC ;IF A(ROM), #$40 OR A(RAM), #$80.
|
||||
|
||||
* INTEGER WAS UP.
|
||||
|
||||
LDA #$20 ;(A) = OPCODE FOR "JSR" INSTRUC.
|
||||
BNE DTRMNBSC ;ALWAYS.
|
||||
|
||||
|
||||
* ACTIVE BASIC FLAG DENOTED THAT A
|
||||
* VERSION OF APPLESOFT WAS ACTIVE,
|
||||
* SO NOW CHECK IF DEALING WITH
|
||||
* A(RAM) OR A(ROM).
|
||||
|
||||
CKBASIC ASL ;MULTIPLY CODE TIMES 2.
|
||||
BPL FORWARM ;BRANCH IF A(RAM).
|
||||
;(IE. A(RAM) YEILDS $40 * 2 = $80
|
||||
;& A(ROM) YEILDS $80 * 2 = $00.)
|
||||
|
||||
* USING A(ROM).
|
||||
|
||||
LDA #$4C ;(A) = OPCODE FOR "JMP" INSTRUC.
|
||||
DTRMNBSC JSR SETROM ;GO TEST CARD OR MOTHERBOARD TO
|
||||
;INSURE THAT DEVICE CONTAINING
|
||||
;ROM VERSION WE WANT IS SELECTED.
|
||||
FORWARM CLC ;(C) = 0, SIGNAL FOR WARMSTART.
|
||||
CMWRMCLD PHP ;SAVE (C) DENOTING WARM OR COLD.
|
||||
JSR INITIOHK ;INITIALIZE THE I/O HOOKS SO THAT
|
||||
;DOS INTERCEPTS ALL IN/OUTPUT.
|
||||
LDA #0
|
||||
STA CIOCUMUL ;SIMULATE A "NOMON" COMMAND.
|
||||
;NOTE: CAN "NOP" OUT THIS INSTRUC
|
||||
;TO DEFEAT "NOMONCIO" WHEN COLD-
|
||||
;OR WARMSTARTING.
|
||||
STA OPUTCOND ;SET CONDITION 0.
|
||||
PLP ;GET SAVED STATUS BACK OFF STK &
|
||||
ROR ;ROTATE (C) INTO HI BIT OF (A) TO
|
||||
STA CONDNFLG ;SET CONDNFLG = $00 FOR WARMSTART
|
||||
;OR CONDNFLG = $80 FOR COLDSTART.
|
||||
BMI LANGCOLD ;BRANCH IF DOING COLDSTART.
|
||||
|
||||
LANGWARM JMP (TOWRMVEC) ;JMPS TO BASIC'S WARMSTART ROUT'N
|
||||
;(RESTART) AT $D43C.
|
||||
|
||||
LANGCOLD JMP (TOCLDVEC) ;JMPS TO BASIC'S COLDSTART ROUT'N
|
||||
;(BASICCLD) AT $E000.
|
||||
|
||||
|
||||
*=================================
|
||||
* INITIAL PROCESSING WHEN FIRST
|
||||
* KEYBOARD INPUT REQUEST IS MADE
|
||||
* BY BASIC AFTER A COLDSTART.
|
||||
*=================================
|
||||
|
||||
* TEST IF USING A(RAM) OR NOT.
|
||||
* ON ENTRY, (A) = CONTENTS OF CONDNFLG.
|
||||
* = $00 = WARM START.
|
||||
* = $01 = READING.
|
||||
* = $80 = COLD START.
|
||||
* = $C0 = USING A(RAM).
|
||||
|
||||
KEYCOLD ASL ;(A) * 2 TO DROP OUT HI BIT.
|
||||
BPL SKPDARAM ;BRANCH IF NOT USING A(RAM).
|
||||
STA ACTBSFLG ;USING A(RAM) - WAS LOADED BY
|
||||
; INTEGER BASIC ROM
|
||||
; - ACTV BSC FLG=$80
|
||||
|
||||
* COPY IMAGE OF A(RAM)'S ENTRY
|
||||
* POINT VECTOR TABLE TO THE
|
||||
* ACTIVE BASIC ENTRY POINT VECTOR
|
||||
* TABLE.
|
||||
|
||||
LDX #12
|
||||
ARAM2BSC LDA IMGARAMV-1,X
|
||||
STA CHAINTRY-1,X
|
||||
DEX
|
||||
BNE ARAM2BSC
|
||||
|
||||
* BLANK OUT THE PRIMARY FILENAME
|
||||
* BUFFER TO MAKE SURE A "HELLO"
|
||||
* FILE WON'T BE RUN.
|
||||
|
||||
LDX #29 ;30 BYTES TO BLANK (29 --> 00).
|
||||
BLNKPRIM LDA SCNDFNBF,X ;COPY BLANK SECONDARY TO PRIMARY.
|
||||
STA PRIMFNBF,X
|
||||
DEX
|
||||
BPL BLNKPRIM
|
||||
|
||||
* BUILD DOS BUFS & SET CONDITION.
|
||||
|
||||
SKPDARAM LDA MAXDFLT ;SET MXFILVAL TO DEFAULT VAL OF 3
|
||||
STA MXFILVAL ;NOTE: DEFAULT VAL CAN BE CHANGED
|
||||
;BY SETTING MAXDFLT BTW'N 1 - 16
|
||||
;AND THEN INITING A DISK.
|
||||
JSR BILDBUFS ;GO BUILD THE DOS BUFFERS.
|
||||
LDA EXECFLAG ;CHK IF AN EXEC FILE IS RUNNING.
|
||||
BEQ SKPDEXEC ;BRANCH IF NOT EXECING.
|
||||
|
||||
PHA ;YES - WE ARE EXECING.
|
||||
JSR PT2EXEC ;GET ADR OF BUF WE'RE EXECING IN.
|
||||
PLA ;RETRIEVE EXEC FLG FROM STK.
|
||||
LDY #0 ;RESERVE DOS BUFFER FOR EXECING
|
||||
STA (A3L),Y ;IN CASE WE WANT TO MODIFY DOS TO
|
||||
;EXEC ON THE BOOT?
|
||||
|
||||
SKPDEXEC JSR RESTAT0 ;SET CONDNFLG=0 SO SIGNAL FILE
|
||||
;NOT BEING READ.
|
||||
;RESET OPUTCOND=0 (TO SIGNAL WANT
|
||||
;TO EVALU8 START OF LINE ON RTN).
|
||||
|
||||
* CHECK IF DISK WAS JUST BOOTED.
|
||||
* (IF JUST BOOTED DISK, NDX2CMD
|
||||
* CONTAINS A $00 WHICH WAS ETCHED
|
||||
* ON THE DISK WHEN THE DISK WAS
|
||||
* ORIGINALLY INITED.)
|
||||
|
||||
LDA NDX2CMD ;WAS LAST CMD AN "INIT"?
|
||||
BNE OLDBOOT ;NO - TAKE BRANCH.
|
||||
|
||||
* DISK WAS JUST BOOTED SO COPY IMAGE
|
||||
* OF DOS'S ENTRY POINT VECTOR TABLE
|
||||
* TO PAGE 3.
|
||||
|
||||
LDX #47 ;48 BYTES TO COPY (47 --> 0).
|
||||
STOR3DOS LDA IMGDOSVT,X ;COPY IMAGE TO PAGE 3.
|
||||
STA PG3DOSVT,X
|
||||
DEX
|
||||
BPL STOR3DOS
|
||||
|
||||
* PROGRAM THE RESET KEY TO POINT AT
|
||||
* DOS'S WARMSTART ROUTINE.
|
||||
*
|
||||
* NOTE THAT THE RESET KEY CAN BE
|
||||
* PROGRAMMED TO PT AT ANY LOCATION
|
||||
* SIMPLY BY PUTTING THE ADR OF THE
|
||||
* TARGET ROUTINE (IN LOW/HI FORMAT)
|
||||
* IN $3F2/$3F3. NEXT, EOR THE
|
||||
* CONTENTS OF $3F3 WITH THE NUMBER
|
||||
* #$A5 AND PUT THE RESULT IN $3F4.
|
||||
* (IF $3F3 EOR #$A5 < > $3F4, THEN
|
||||
* DISK REBOOTS & A COLDSTART IS DONE.)
|
||||
|
||||
LDA IMGDOSVT+2 ;WRITE OVER OLD (OUT-DATED) IMAGE
|
||||
STA RESETVEC+1 ;WHICH CONTAINED A "JSR MON"
|
||||
EOR #$A5 ;INSTRUC APPLIC TO NON-AUTOSTART.
|
||||
STA VLDBYTE ;SET VALIDATION (POWER UP) BYTE.
|
||||
LDA IMGDOSVT+1
|
||||
STA RESETVEC
|
||||
|
||||
* SET THE COMMAND INDEX TO RUN
|
||||
* THE "HELLO" FILE.
|
||||
|
||||
LDA #6 ;CMD INDEX FOR "RUN".
|
||||
;(CAN BE CHANGED TO "BRUN", ETC.)
|
||||
BNE DOPENDNG ;ALWAYS.
|
||||
|
||||
* CHECK IF A COMMAND IS PENDING.
|
||||
|
||||
OLDBOOT LDA NEXTCMD
|
||||
BEQ NOPEND ;NO CMD PENDING.
|
||||
|
||||
* GO DO THE PENDING COMMAND. IF THE
|
||||
* DISK WAS JUST BOOTED, THEN RUN THE
|
||||
* "HELLO" FILE. NOTE THAT THE ACTUAL
|
||||
* NAME OF THE HELLO FILE RESIDES IN
|
||||
* THE PRIMARY FILENAME BUFFER. IT
|
||||
* WAS WRITTEN TO THE DISK AS PART OF
|
||||
* THE DOS IMAGE WHEN THE DISK WAS INITED.
|
||||
* THERE4, IF YOU WANT TO CHANGE THE
|
||||
* NAME OF THE HELLO FILE, YOU MUST:
|
||||
* (1) CHNG NAME IN FILENAME FIELD
|
||||
* OF DIRECTORY SEC. (EASIEST JUST
|
||||
* TO USE THE RENAME CMD.)
|
||||
* (2) ZAP PRIMARY NAME BUF ON DISK
|
||||
* (TRK$01/SEC$09/OFFSETS$75-$92).
|
||||
|
||||
DOPENDNG STA NDX2CMD ;SET CMD INDEX & GO DO CMD.
|
||||
JMP DODOSCMD
|
||||
NOPEND RTS
|
||||
|
||||
|
||||
*=================================
|
||||
* IMAGE OF DOS VECTOR TABLE.
|
||||
* (COPIED TO PAGE 3, $3D0 - $3FF.)
|
||||
*=================================
|
||||
|
||||
; PAGE-3 ADDR & FUNCTION
|
||||
|
||||
IMGDOSVT JMP DOSWARM ;$3D0 - GO TO DOS'S WARM START
|
||||
;ROUTINE. LEAVE PGRM INTACT.
|
||||
JMP DOSCOLD ;$3D3 - GO TO DOS'S COLD START
|
||||
;ROUT'N. RESET HIMEM, REBUILD DOS
|
||||
;BUFS & WIPE OUT PRGM.
|
||||
JMP FMXTNTRY ;$3D6 - ALLOW USER TO ACCESS FM
|
||||
;VIA HIS OWN ASSEMBLY LANG PRGMS.
|
||||
JMP ENTERWTS ;$3D9 - ALLOW USER TO ACCESS RWTS
|
||||
;VIA HIS OWN ASSEMBLY LANG PRGMS.
|
||||
LDA ADFMPARM+1 ;$3DC - LOCATE FM PARAMETER LIST.
|
||||
LDY ADFMPARM
|
||||
RTS
|
||||
|
||||
LDA ADRIOB+1 ;$3E3 - LOCATE RWTS'S I/O BLOCK.
|
||||
LDY ADRIOB
|
||||
RTS
|
||||
|
||||
JMP INITIOHK ;$3EA - PT I/O HOOKS AT DOS'S
|
||||
;INTERCEPT HANDLERS.
|
||||
NOP
|
||||
NOP
|
||||
JMP OLDBRK ;$3EF - GOES TO MONITOR'S ROUTINE
|
||||
;WHICH HANDLES "BRK" INSTRUC'S.
|
||||
JMP MON ;AFTER THIS INSTRUCTION IS COPIED
|
||||
;TO PAGE 3 (AT $3F2 - $3F4), THE
|
||||
;ROUTINE AT $9E30 OVERWRITES THE
|
||||
;PAGE-3 IMAGE 2 PROGRAM THE RESET
|
||||
;KEY. THIS OVERWRITTING IS DONE 2
|
||||
;ACCOMMODATE NEWER "AUTOSTART"
|
||||
;ROM USED IN THE APPLE II+, IIE &
|
||||
;IIC MACHINES. THE PAGE-3 LOC'S
|
||||
;ARE DESCRIBED BELOW:
|
||||
;$3F2/$3F3 - ADR OF RESET HNDLING
|
||||
;ROUT'N (IN LOW/HI FORMAT).
|
||||
;NORMALLY=ADR OF DOSWARM ($9DBF).
|
||||
;$3F4 - IMG OF VALIDATION BYTE.
|
||||
;NORMALLY CONTAINS #$38 CAUSE:
|
||||
; #$9D EOR #$A5 = #$38.
|
||||
|
||||
JMP MONRTS ;$3F5 - DISABLE &-VECTOR.
|
||||
JMP MON ;$3F8 - LET CTL-Y ENTER MONITOR.
|
||||
JMP MON ;$3FB - HNDL NON-MASK INTERUPTS.
|
||||
DA MON ;ROUT'N 2 HNDL MASKABLE INTERUPTS
|
||||
|
||||
|
||||
*==================================
|
||||
* DOS'S INPUT INTERCEPT ROUTINE.
|
||||
* (INTERCEPTS ALL INPUT FROM
|
||||
* KEYBOARD OR DISK.)
|
||||
*==================================
|
||||
|
||||
INPTINCP JSR PREP4DOS ;SAVE THE REGS & RESTORE I/O HKS
|
||||
;TO PT TO THE TRUE I/O HANDLERS.
|
||||
;ADJUST STK PTR & SAVE IT SO WE
|
||||
;CAN LATER RTN 2 THE ROUTINE THAT
|
||||
;CALLED ROUTINE THAT CONTAINED
|
||||
;THE "JSR PREP4DOS" INSTRUCTION.
|
||||
LDA CONDNFLG ;TEST IF DOING WARMSTART.
|
||||
BEQ INPUTWRM ;YES - BRANCH IF WARM.
|
||||
|
||||
* READING FILE OR COLDSTARTING.
|
||||
|
||||
PHA ;SAVE THE CONDITION FLAG.
|
||||
LDA ASAVED ;GET THE SUBSTITUTE CURSOR & PUT
|
||||
STA (BASL),Y ;IT BACK ON THE SCREEN.
|
||||
PLA ;GET CONDITION FLAG BACK IN (A).
|
||||
BMI INPUTCLD ;BRANCH FOR COLD.
|
||||
JMP READTEXT ;READ FILE BYTE.
|
||||
|
||||
* DOING A COLDSTART.
|
||||
|
||||
INPUTCLD JSR KEYCOLD ;SET IMPORTANT PAGE 3 VECTORS.
|
||||
;SET MXFILVAL=3 & BUILD DOS BUFS.
|
||||
;SET WARMSTART FLAG.
|
||||
;EXECUTE PENDING COMMAND.
|
||||
LDY CH ;GET HORZ CURSOR POS'N.
|
||||
LDA #$60 ;GET CURSOR.
|
||||
STA (BASL),Y ;REINSTATE CURSOR ON SCREEN.
|
||||
|
||||
* USING WARMSTART STATUS.
|
||||
* AT THIS POINT IN TIME, BOTH
|
||||
* CONDNFLG & OPUTCOND = 0 FOR
|
||||
* WARM- & COLDSTARTS.
|
||||
|
||||
INPUTWRM LDA EXECFLAG ;ARE WE EXECING?
|
||||
BEQ INPTNOXC ;NO.
|
||||
JSR READEXEC ;YES - GO READ AN EXEC FILE BYTE.
|
||||
INPTNOXC LDA #3 ;SET OUTPUT CONDITION = 3 CAUSE
|
||||
STA OPUTCOND ;WANT TO PROCESS INPUT INFO.
|
||||
JSR RESTOREG ;RESTORE (A), (Y) & (X) REGS.
|
||||
JSR TOTRUIN ;GET CHAR & PUT IT ON SCREEN VIA
|
||||
;THE TRUE OUTPUT HANDLER (COUT1).
|
||||
STA ASAVED ;SAVE CHAR & (X).
|
||||
STX XSAVED
|
||||
JMP DOSEXIT ;EXIT DOS.
|
||||
|
||||
TOTRUIN JMP (KSW) ;JUMP TO THE TRUE INPUT HANDLER.
|
||||
|
||||
|
||||
*=================================
|
||||
* DOS'S OUTPUT INTERCEPT ROUTINE.
|
||||
* (INTERCEPTS ALL OUPUT TO SCREEN
|
||||
* OR OTHER PERIPHERALS.)
|
||||
*=================================
|
||||
|
||||
OPUTINCP JSR PREP4DOS ;SAVE REGS & RESTORE I/O HKS 2 PT
|
||||
;2 TRUE I/O HANDLERS. ADJUST STK
|
||||
;PTR & SAVE IT SO CAN LATER RTN
|
||||
;TO THE ROUTINE THAT CALLED THE
|
||||
;ROUTINE THAT CONTAINED THE
|
||||
;"JSR PREP4DOS" INSTRUCTION.
|
||||
|
||||
* USE CURRENT OPUTCOND TO INDEX
|
||||
* TABLE CONTAINING ADDRS (MINUS 1)
|
||||
* OF THE OUTPUT CONDITION HANDLERS.
|
||||
* DO A "STACK JUMP" TO THE APPROPRIATE
|
||||
* HANDLER.
|
||||
|
||||
LDA OPUTCOND
|
||||
ASL ;TIMES 2 CAUSE 2 BYTES / ADDRESS.
|
||||
TAX ;SET (X) TO INDEX TABLE OF ADRS.
|
||||
LDA OUTHNDTB+1,X ;PUT ADR OF OUTPUT HNDLR ON STK
|
||||
PHA ;(HI BYTE FIRST) & THEN DO A
|
||||
LDA OUTHNDTB,X ;"STACK JUMP" TO THE APPROPRIATE
|
||||
PHA ;HANDLER.
|
||||
LDA ASAVED ;GET CHAR TO BE PRINTED.
|
||||
RTS ;EXECUTE THE STACK JUMP.
|
||||
|
||||
|
||||
*================================
|
||||
* PREPARE FOR PROCESSING BY DOS.
|
||||
* SAVE THE REGS & RESET THE I/O
|
||||
* HOOKS TO POINT TO THE TRUE I/O
|
||||
* HANDLERS.
|
||||
*================================
|
||||
|
||||
PREP4DOS STA ASAVED ;SAVE (A), (Y) & (X) REGS.
|
||||
STX XSAVED
|
||||
STY YSAVED
|
||||
TSX ;ADJUST STK PTR & SAVE IT SO WHEN
|
||||
INX ;WE LATER RESTORE IT & HIT AN
|
||||
INX ;RTS, WE CAN RTN 2 ROUTINE THAT
|
||||
STX STKSAVED ;CALLED ROUTINE THAT CONTAINED
|
||||
;THE "JSR PREP4DOS" INSTRUCTION.
|
||||
|
||||
* DISCONNECT DOS - THIS ENTRY POINT
|
||||
* IS FREQUENTLY USED BY ASSEMBLY
|
||||
* LANGUAGE PROGRAMMERS TO DISCONNECT
|
||||
* DOS COMPLETELY.
|
||||
|
||||
UNCONDOS LDX #3 ;RESTORE THE I/O HKS TO PT TO THE
|
||||
;TRUE I/O HANDLERS, EX:
|
||||
SETRUHKS LDA CSWTRUE,X ; KSWTRUE: KEYIN --> KSW: KEYIN
|
||||
STA CSW,X ; CSWTRUE: COUT1 --> CSW: COUT1
|
||||
DEX
|
||||
BPL SETRUHKS ;4 BYTES (0 TO 3) TO MOVE.
|
||||
RTS
|
||||
|
||||
|
||||
*=================================
|
||||
* OUTPUT HANDLER 0.
|
||||
* (EVALUATE START OF LINE.)
|
||||
*=================================
|
||||
|
||||
OPUTHDL0 LDX RUNTRUPT ;CONTAINS A NONZERO VALUE IF RUN
|
||||
BEQ NONTRUPT ;CMD WAS INTERRUPTED TO DO A LOAD
|
||||
JMP FINSHRUN ;FINISH OFF THE RUN COMMAND.
|
||||
|
||||
* FILE NOT BEING READ.
|
||||
|
||||
NONTRUPT LDX CONDNFLG ;GET CONDITION FLAG. CHECK IF WE
|
||||
;ARE DOING A WARMSTART ($00),
|
||||
;COLDSTART ($80), USING A(RAM)
|
||||
;($C0) OR DOING A READ ($01).
|
||||
BEQ SETIGNOR ;BRANCH IF WARMSTARTING.
|
||||
|
||||
* DOING COLDSTART, READING FILE OR USING A(RAM).
|
||||
* CHECK (A) TO SEE IF USING "?" ASSOCIATED
|
||||
* WITH READING AN INPUT STATEMENT.
|
||||
|
||||
CMP #"?" ;IF READING, USING "?" AS PROMPT.
|
||||
BEQ OPUTHDL6 ;GO DSPLY INPUT CONDITIONALLY IF
|
||||
;GETTING READY 2 READ A TEXT FILE
|
||||
;BYTE.
|
||||
CMP PROMPT ;ARE WE PRINTING A PROMPT?
|
||||
BEQ SET2EVAL ;BRANCH IF ABOUT TO PRINT PROMPT.
|
||||
SETIGNOR LDX #2 ;SET CONDITION 2 FOR DEFAULT TO
|
||||
STX OPUTCOND ;SIGNAL SHOULD IGNORE NON-DOS
|
||||
;COMMANDS.
|
||||
|
||||
CMP DCTRLCHR ;IS CHAR = DOS'S CTRL CHAR?
|
||||
BNE OPUTHDL2 ;NO.
|
||||
DEX ;LINE STARTED WITH DOS'S CTRL CHR
|
||||
STX OPUTCOND ;SO SET CONDITION 1.
|
||||
DEX ;(X) = 1 --> 0.
|
||||
STX NDX2INBF ;INDEX TO 1RST POS'N IN INPUT BUF
|
||||
|
||||
|
||||
*=================================
|
||||
* OUTPUT HANDLER 1.
|
||||
* - COLLECT THE DOS COMMAND.
|
||||
* (IE. - STICK CHAR IN THE INPUT
|
||||
* BUF & THEN GO DISPLAY CHAR OR
|
||||
* ELSE GO PARSE CMD.)
|
||||
*=================================
|
||||
|
||||
OPUTHDL1 LDX NDX2INBF ;GET INDEX TO INPUT BUFFER.
|
||||
PUTINBUF STA BUF200,X ;PUT CHAR IN INPUT BUFFER.
|
||||
INX ;KICK UP INDEX 4 NEXT BUF POS'N.
|
||||
STX NDX2INBF
|
||||
CMP #$8D ;WAS CHAR A <CR>?
|
||||
BNE DSPLYCMD ;NO.
|
||||
JMP PARSECMD ;YES - GOT END OF INPUT, SO NOW
|
||||
; SEE IF IT IS A DOS CMD.
|
||||
|
991
textfiles.com/apple/ANATOMY/t.dos.9f23.a232.txt
Normal file
991
textfiles.com/apple/ANATOMY/t.dos.9f23.a232.txt
Normal file
@@ -0,0 +1,991 @@
|
||||
*=================================
|
||||
* OUTPUT HANDLER 2.
|
||||
* (IGNORE NON-DOS COMMAND.)
|
||||
*=================================
|
||||
|
||||
OPUTHDL2 CMP #$8D ;<CR>?
|
||||
BNE DSPLYALL ;NO - (WAS AN "RH BRACKETT"?)
|
||||
SET2EVAL LDX #0 ;SET CONDITION0 - EVALUATE START
|
||||
STX OPUTCOND ;OF LINE.
|
||||
JMP DSPLYALL ;GO DISPLAY CHAR UNCONDITIONALLY.
|
||||
|
||||
|
||||
*=================================
|
||||
* OUTPUT HANDLER 3.
|
||||
* (PROCESS INPUT INFO.)
|
||||
*=================================
|
||||
|
||||
OPUTHDL3 LDX #0 ;SET CONDITION 0 WHEN INPUT ENDS.
|
||||
STX OPUTCOND
|
||||
CMP #$8D ;<CR>?
|
||||
BEQ ASUMIMED ;YES.
|
||||
|
||||
|
||||
TESTEXEC LDA EXECFLAG ;ARE WE EXECING?
|
||||
BEQ DSPLYALL ;NO.
|
||||
BNE DSPLYINP ;YES. EXECFLAG CONTAINS THE 1RST
|
||||
;CHR OF NAME OF THE EXEC FILE.
|
||||
|
||||
ASUMIMED PHA ;SAVE CHAR ON STK.
|
||||
SEC ;(C)=1, DFLT, ASSUME IMMED MODE.
|
||||
LDA EXECFLAG ;ARE WE EXECING?
|
||||
BNE TESTMODE ;BRANCH IF EXECING.
|
||||
JSR CKBSCRUN ;NOT EXECING, SO SEE IF BASIC IS
|
||||
;RUNNING A PRGM OR NOT.
|
||||
;(C) = 0, EITHER BASIC RUNNING.
|
||||
;(C) = 1 IF IMMEDIATE.
|
||||
TESTMODE PLA ;RETRIEVE CHAR FROM STK.
|
||||
BCC TESTEXEC ;BASIC RUNNING, DSPLY INPUT & XIT
|
||||
|
||||
* EXECING OR IN IMMEDIATE MODE
|
||||
* (CAUSE (C) = 1).
|
||||
|
||||
LDX XSAVED ;RETRIEVE (X).
|
||||
JMP PUTINBUF ;GO PUT CHR IN INPUT BUF (COND 1)
|
||||
|
||||
|
||||
*=================================
|
||||
* OUTPUT HANDLER 4.
|
||||
* (WRITING DATA.)
|
||||
*=================================
|
||||
|
||||
OPUTHDL4 CMP #$8D ;<CR>?
|
||||
BNE CMWRTBYT ;NO.
|
||||
LDA #5 ;SET CONDITION 5.
|
||||
STA OPUTCOND
|
||||
CMWRTBYT JSR WRITEXT ;GO WRITE DATA BYTE.
|
||||
JMP DSPLYOUT ;DISPLAY OUTPUT CONDITIONALLY.
|
||||
|
||||
|
||||
*===================================
|
||||
* OUTPUT HANDLER 5.
|
||||
* (EVALUATE START OF DATA TO WRITE)
|
||||
*===================================
|
||||
|
||||
OPUTHDL5 CMP DCTRLCHR ;IS CHAR = DOS'S CTRL CHAR?
|
||||
;************* NOTE ************
|
||||
;* DOS'S CTRL CHAR CANCELS THE *
|
||||
;* WRITE MODE. *
|
||||
;*******************************
|
||||
|
||||
BEQ OPUTHDL0 ;YES - SO GO TO CONDITION 0.
|
||||
CMP #$8A ;IS CHAR AN <LF>?
|
||||
BEQ CMWRTBYT ;YES -GO WRITE IT, STAY IN COND 5
|
||||
LDX #4 ;NO -RESET TO CONDITION4 - SIGNAL
|
||||
STX OPUTCOND ;WANT TO WRITE ANOTHER LINE.
|
||||
BNE OPUTHDL4 ;ALWAYS.
|
||||
|
||||
|
||||
*=================================
|
||||
* OUTPUT HANDLER 6.
|
||||
* (SKIP THE QUESTION MARK PROMPT.)
|
||||
*=================================
|
||||
|
||||
OPUTHDL6 LDA #0 ;SET CONDITION 0.
|
||||
STA OPUTCOND
|
||||
BEQ DSPLYINP ;ALWAYS.
|
||||
;GO CONDITIONALLY DISPLAY INPUT.
|
||||
|
||||
|
||||
*=================================
|
||||
* FINISH OFF THE RUN COMMAND
|
||||
* (BECAUSE IT WAS INTERRUPTED TO
|
||||
* DO A LOAD.)
|
||||
*=================================
|
||||
|
||||
FINSHRUN LDA #0 ;ZERO OUT THE RUN INTERRUPT FLAG.
|
||||
STA RUNTRUPT
|
||||
JSR INITIOHK ;RESET I/O HOOKS 2 PT AT DOS.
|
||||
JMP RUNFPINT ;JUMP BACK INTO THE RUN COMMAND
|
||||
;TO FINISH IT OFF.
|
||||
;************* NOTE *************
|
||||
;* THE STACK WAS RESET SO WE *
|
||||
;* RETURN AT THE CORRECT LEVEL. *
|
||||
;********************************
|
||||
|
||||
|
||||
*======================================
|
||||
* COMMON ROUT'N TO FINISH OFF MOST DOS
|
||||
* CMDS. THE WRITE & READ CMD HNDLRS
|
||||
* RTN HERE. CMDWRITE ($A510) SETS
|
||||
* OPUTCOND=5 BEFORE RETURNING.
|
||||
* CMDREAD ($A51B) RTNS WITH CONDNFLG=1.
|
||||
*======================================
|
||||
|
||||
FINSHCMD LDA BUF200 ;GET FIRST CHAR IN BUF.
|
||||
CMP DCTRLCHR ;WAS CMD DONE VIA DOS'S CTRL CHR?
|
||||
BEQ DSPLYCMD ;YES.
|
||||
|
||||
|
||||
* CANCEL CMD BY REPLACING THE CHAR
|
||||
* WITH A <CR> & THEN FALL THRU TO
|
||||
* CONTINUE THE EXIT SEQUENCE.
|
||||
|
||||
LDA #$8D ;<CR>
|
||||
STA BUF200 ;SET 200: 8D.
|
||||
LDX #0 ;SET INDEX TO START OF INPUT BUF.
|
||||
STX XSAVED
|
||||
|
||||
|
||||
*---------------------------------------
|
||||
* DISPLAY CHARACTER OUPUT CONDITIONALLY.
|
||||
* (THAT IS, PREPARE TO SEND THE CHAR
|
||||
* TO THE OUTPUT DEVICE.)
|
||||
*---------------------------------------
|
||||
|
||||
DSPLYCMD LDA #%01000000 ;SET BIT6 TO SEE IF USING "MON C"
|
||||
BNE DSPLYCHR ;ALWAYS.
|
||||
DSPLYOUT LDA #%00010000 ;SET BIT4 TO SEE IF USING "MON O"
|
||||
BNE DSPLYCHR ;ALWAYS.
|
||||
DSPLYINP LDA #%00100000 ;SET BIT5 TO SEE IF USING "MON I"
|
||||
DSPLYCHR AND CIOCUMUL ;TEST FLAG: SEE IF SHOULD DSPLY.
|
||||
BEQ DOSEXIT ;NO DISPLAY -SPECIFIC BIT WAS OFF
|
||||
;MON/NOMON CLR/SET SPECIFIC BITS.
|
||||
|
||||
|
||||
*---------------------------------
|
||||
* DISPLAY THE CHARACTER.
|
||||
*---------------------------------
|
||||
|
||||
DSPLYALL JSR RESTOREG ;RESTORE (A), (Y) & (X) REGS.
|
||||
JSR GODSPLY ;OUTPUT CHR VIA TRU OUTPUT HNDLR
|
||||
STA ASAVED ;SAVE (A), (Y) & (X) REGS.
|
||||
STY YSAVED
|
||||
STX XSAVED
|
||||
|
||||
|
||||
*=================================
|
||||
* ROUTINE TO EXIT DOS.
|
||||
* POINT THE I/O HKS AT DOS AND
|
||||
* RESET THE STACK POINTER.
|
||||
*---------------------------------
|
||||
|
||||
DOSEXIT JSR INITIOHK ;RESET I/O HKS TO POINT TO DOS.
|
||||
LDX STKSAVED ;RETRIEVE SAVED STACK POINTER.
|
||||
TXS
|
||||
RESTOREG LDA ASAVED ;RESTORE (A), (Y) & (X) REGS.
|
||||
LDY YSAVED
|
||||
LDX XSAVED
|
||||
SEC ;WHY?????
|
||||
RTS ;************ NOTE **************
|
||||
;* IF THIS RTS IS ENCOUNTERED *
|
||||
;* VIA A FALL THRU FROM DOSEXIT,*
|
||||
;* THEN RTN TO THE ROUTINE THAT *
|
||||
;* CALLED THE ROUTINE THAT *
|
||||
;* CONTAINED THE "JSR PREP4DOS" *
|
||||
;* INSTRUCTION. *
|
||||
;********************************
|
||||
|
||||
|
||||
*=================================
|
||||
* CHARACTER OUTPUT HANDLER.
|
||||
*=================================
|
||||
|
||||
GODSPLY JMP (CSW) ;USUALLY POINTS 2 THE TRUE OUTPUT
|
||||
;HANDLER (COUT1, $FDF0 IF SCRN).
|
||||
CRVIADOS LDA #$8D ;<CR>.
|
||||
JMP GODSPLY ;USUALLY PRINTS A <CR> THRU THE
|
||||
;OUTPUT HANDLER (COUT1). HOWEVER,
|
||||
;WHEN ACCESSED BY RUNFPINT($A4DC)
|
||||
;DURING A COLDSTART, GOES INTO
|
||||
;DOS'S OUTPUT INTERCEPT ROUTINE
|
||||
;(OPUTINCP, $9EBD).
|
||||
|
||||
|
||||
*=================================
|
||||
* DOS'S COMMAND PARSING ROUTINE.
|
||||
*=================================
|
||||
|
||||
PARSECMD LDY #$FF ;INITIALIZE INDEX TO CMD TXT TBL.
|
||||
STY NDX2CMD
|
||||
INY ;(Y) = 0.
|
||||
STY NEXTCMD ;SIGNAL NO PENDING COMMAND FOR
|
||||
;NEXT TIME AROUND.
|
||||
GETCHR1 INC NDX2CMD ;INDEX TO COMMAND TEXT TABLE.
|
||||
;(0 ON ENTRY.)
|
||||
LDX #0 ;INITIALIZE INDEX TO INPUT CHARS.
|
||||
PHP ;SAVE STATUS (WITH Z=1) ON STK.
|
||||
;(DFLT STATUS, ASSUME CHRS MTCH.)
|
||||
LDA BUF200,X ;GET FIRST CHAR IN INPUT BUFFER.
|
||||
CMP DCTRLCHR ;IF IT IS NOT DOS'S CTRL CHAR,
|
||||
BNE SAVLINDX ;SET LINE INDEX TO 0. IF IT IS
|
||||
INX ;DOS'S CTRL CHAR, SET INDEX TO 1
|
||||
;SO SKIP CTRL CHAR.
|
||||
|
||||
* DOES THE INPUT CHAR EQUAL A CHAR
|
||||
* IN DOS'S CMD TEXT TABLE (CMDTXTBL)?
|
||||
* (NOTE: LAST CHAR IN @ CMD IS NEGATIVE
|
||||
* ASCII, REST OF CHARS IN A GIVEN CMD
|
||||
* ARE POSITIVE ACSII.)
|
||||
|
||||
SAVLINDX STX NDX2INBF ;SAVE INDEX TO INPUT BUF.
|
||||
INVSCMD JSR PURGECMD ;GET CHAR FROM INPUT BUFFER
|
||||
;(IGNORE SPACES).
|
||||
AND #$7F ;STRIP HI BIT OFF OF CHAR.
|
||||
EOR CMDTXTBL,Y ;DOES INPUT CHAR MATCH A CMD CHR?
|
||||
;IF POS INPUT CHAR/POS ASCII CMD
|
||||
;CHAR MATCH, THEN (A) = 0.
|
||||
;IF POS INPUT CHR / NEG ASCII CMD
|
||||
;CHAR MATCH, THEN (A) = $80.
|
||||
INY ;KICK UP INDEX TO NEXT CHAR IN
|
||||
;THE COMMAND TEXT TABLE.
|
||||
ASL ;IF POS/POS MATCH (A)=0 & (C)=0.
|
||||
;IF POS/NEG MTCH (A)=$80 & (C)=1.
|
||||
BEQ CKIFCHRS ;CHAR MATCHED SO GO CHK CARRY.
|
||||
|
||||
* INPUT CHARS < > TEXT CMD CHAR.
|
||||
|
||||
PLA ;PULL SAVED STATUS OFF STK TO CLR
|
||||
;Z-FLG (CAUSE IF SAVED STATUS
|
||||
;HAD (Z) OR (C) = 1, THEN NEW (A)
|
||||
;WILL HAVE AT LEAST 1 BIT SET SO
|
||||
;THEN (A) < > 0.)
|
||||
PHP ;PUSH STATUS ON STK (WITH Z-FLAG
|
||||
;CLR & (C) CONDITIONED AS PER
|
||||
;ABOVE "ASL" INSTRUCTION.
|
||||
|
||||
* SEE IF THER ARE ANY MORE CHARS TO
|
||||
* CHECK IN THE TEXT OF A GIVEN CMD.
|
||||
|
||||
CKIFCHRS BCC INVSCMD ;IF (C)=0, MORE CHARS TO CHK IN
|
||||
;GIVEN CMD LISTED IN TABLE.
|
||||
;IF (C)=1, CHKD LAST CHR IN TBL.
|
||||
|
||||
* FINISHED CHECKING TEXT
|
||||
* OF A PARTICULAR COMMAND.
|
||||
|
||||
PLP ;GET STATUS OFF STACK.
|
||||
|
||||
* DID COMMAND MATCH?
|
||||
|
||||
BEQ PRPDOCMD ;IF LAST CHR MATCHED, THEN ENTIRE
|
||||
;CMD MATCHED SO GO PROCESS CMD.
|
||||
|
||||
* CHECK IF SEARCHED ENTIRE TABLE.
|
||||
|
||||
LDA CMDTXTBL,Y ;LAST CHAR DIDN'T MATCH, SO NOT
|
||||
BNE GETCHR1 ;CORRECT CMD. THERE4, GO CHK IF
|
||||
;NEXT CHAR BYTE IN TABLE IS $00.
|
||||
;IF NOT $00, GO CHK REMAINING
|
||||
;CMDS IN TBL. IF IT IS $00, THEN
|
||||
;DONE ENTIRE TBL & NO CMDS MTCHD.
|
||||
|
||||
* EITHER AT END OF TABLE AND NO
|
||||
* CMDS MATCHED OR ELSE DETECTED A
|
||||
* BSAVE CMD WITH NO ACCOMPANYING
|
||||
* A- OR L- PARAMETERS.
|
||||
|
||||
* CHECK IF DOS'S CTRL CHAR WAS USED.
|
||||
|
||||
CKIFCTRL LDA BUF200 ;IS 1RST CHAR IN THE INPUT BUFFER
|
||||
CMP DCTRLCHR ;EQUAL TO DOS'S CTRL CHAR?
|
||||
BEQ CHKIFCR ;YES.
|
||||
JMP DSPLYALL ;NO -GO DSPLY CHR & THEN XIT DOS.
|
||||
|
||||
* WAS DOS'S CTRL CHAR THE ONLY CHAR ON LINE?
|
||||
|
||||
CHKIFCR LDA BUF200+1 ;GET 2ND BYTE IN INPUT BUFFER.
|
||||
CMP #$8D ;WAS IT A <CR>?
|
||||
BNE PRSYNERR ;NO -NOT SIMPLY DEALING WITH CMD
|
||||
;CANCELLING DOS CTRL CHR AND <CR>
|
||||
;SO GO ISSUE A SYNTAX-ERROR MSG.
|
||||
JSR RESTAT0 ;YES - SET CONDITION 0.
|
||||
JMP DSPLYCMD ;GO DISPLAY <CR>.
|
||||
PRSYNERR JMP SYNTXERR ;EITHER A CTRL CHR DENOTED THAT A
|
||||
;DOS CMD WAS WANTED & NO MATCHING
|
||||
;CMD WAS FOUND (ELSE DETECTED A
|
||||
;BSAVE CMD WITH NO A- OR L-PARMS)
|
||||
;SO GO GIVE DOS'S SYNTAX ERR MSG.
|
||||
|
||||
|
||||
*========================================
|
||||
* PREPARE TO EXECUTE THE DOS COMMAND.
|
||||
* ON ENTRY - A DOS CMD WAS PARSED.
|
||||
* - NDX2CMD = COMMAND CODE.
|
||||
* - I/O HKS PT TO TRUE HANDLERS.
|
||||
* NOTE THAT THIS ROUTINE MAKES EXTENSIVE
|
||||
* USE OF A TABLE (CMDATTRB, $A909-$A940)
|
||||
* WHICH CONTAINS AN ENCODED LIST OF THE
|
||||
* ATTRIBUTES ASSOCIATED WITH @ COMMAND.
|
||||
*========================================
|
||||
|
||||
PRPDOCMD ASL NDX2CMD ;DOUBLE INDEX CAUSE 2 BYTES/ADDR
|
||||
LDY NDX2CMD ;IN TABLE OF DOS CMD ENTRY PTS.
|
||||
JSR CKBSCRUN ;CHECK IF BASIC IS RUNNING A PGM:
|
||||
BCC CHKIFRUN ; (C)=0= BASIC RUNNING.
|
||||
; (C)=1= BASIC NOT RUNNING.
|
||||
|
||||
* USING IMMEDIATE MODE, SO NOW CHK
|
||||
* IF CMD IS LEGAL IN THAT MODE.
|
||||
|
||||
IMMED LDA #%00000010 ;CHK BIT1 OF CMDATTRB TO SEE IF
|
||||
AND CMDATTRB,Y ;CMD IS LEGAL IN THAT MODE.
|
||||
BEQ CHKIFRUN ;BRANCH IF LEGAL.
|
||||
NODIRCMD LDA #15 ;SET RETURN CODE TO SIGNAL THAT
|
||||
JMP ERRHNDLR ;WE GOT A NOT-DIRECT-COMMAND ERR.
|
||||
|
||||
* RUNNING PROGRAM OR ELSE COMMAND
|
||||
* COMPLIES WITH IMMEDIATE MODE.
|
||||
|
||||
CHKIFRUN CPY #6 ;CHECK TO SEE IF CMD WAS A "RUN".
|
||||
BNE TST4NAME ;BRANCH IF NOT.
|
||||
STY PROMPT ;PUT AN $06 IN PROMPT IF COMMAND
|
||||
;WAS A "RUN".
|
||||
|
||||
* CHECK TO SEE IF A FILENAME
|
||||
* IS APPLICABLE TO THE COMMAND.
|
||||
|
||||
TST4NAME LDA #%00100000 ;BIT5 = 1 IF FILENAME APPLICABLE.
|
||||
AND CMDATTRB,Y
|
||||
BEQ FNOTAPPL ;BRANCH IF NAME NOT APPLICABLE.
|
||||
;(EX. CMDS: CATALOG, PR#, IN#,
|
||||
;MON, NOMON, MAXFILES, FP & INT.)
|
||||
|
||||
* FILENAME APPLICABLE TO CMD ISSUED
|
||||
* SO BLANK OUT FILENAME BUFFERS IN
|
||||
* ANTICIPATION OF RECEIVING NAME.
|
||||
|
||||
FNXPCTD JSR BLNKFNBF ;BLANK BOTH 1RST & 2ND NAME BUFS.
|
||||
PHP ;SAVE STATUS (Z-FLAG=1) ON STK.
|
||||
;NOTE: Z-FLAG USED TO SIGNAL IF
|
||||
; DEALING WITH PRIMARY OR
|
||||
; SECONDARY NAME BUFFERS.
|
||||
FNAMCHR1 JSR PURGECMD ;GET 1RST CHAR IN NAME. (IGNORE
|
||||
;LEADING SPACES.)
|
||||
BEQ DONEFN ;GOT "," OR <CR> - CHK IF DONE
|
||||
;(CAUSE THESE NOT LEGAL 4 NAME).
|
||||
|
||||
* CHK IF CHAR IS LEGAL TENDER FOR NAME.
|
||||
* (KNOW IT WASN'T A <SPC>, "," OR <CR>
|
||||
* BUT IT STILL MAY NOT BE LEGAL.)
|
||||
|
||||
ASL ;(C) = HI BIT OF CHAR.
|
||||
BCC LGLFNCHR ;IF INV OR FLSH, OK FOR NAME.
|
||||
;BUT, NOTE THAT THEY CAN ONLY BE
|
||||
;POKED INTO INPUT BUF FROM A
|
||||
;RUNNING PRGM. (THIS TECHNIQUE IS
|
||||
;USED IN MANY PROTECT'N SCHEMES.)
|
||||
BMI LGLFNCHR ;ACTUALLY TESTING BIT6 CAUSE JUST
|
||||
;DID AN "ASL".IF BYTE IS 11XXXXXX
|
||||
;(IE. $C0, NORMAL "@" OR GREATER)
|
||||
;CHAR IS LEGAL FOR NAME.
|
||||
JMP CKIFCTRL ;GOT ILLEGAL NAME CHAR SO GO DO A
|
||||
;FEW MORE CHKS ON CTRL CHRS, ETC
|
||||
;& EXIT DOS. (WAS IT A CTRL CHAR,
|
||||
;NUMBER OR ONE OF THE FOLLOWING
|
||||
;NORMAL CHARS:SPC, !, ", #, $, %,
|
||||
;&, ', (, ), *, +, COMMA, -, ., /
|
||||
;:, ;, <, -, >, OR ?
|
||||
|
||||
* CHAR IS LEGAL TENDER FOR NAME.
|
||||
|
||||
LGLFNCHR ROR ;RESTORE NAME CHAR.
|
||||
JMP SVFNCHAR ;SAVE IT IN 1RST OR 2ND NAME BUF.
|
||||
|
||||
* PROCESS REST OF CHARS.
|
||||
|
||||
NCHR2ETC JSR CMDCHAR ;GET 2ND & SUB'QUENT CHRS IN NAME
|
||||
BEQ DONEFN ;GOT A <CR> OR "," SO GO CHK IF
|
||||
;JUST FINISHED SECOND FILENAME.
|
||||
|
||||
* PUT CHARS IN FILENAME BUF.
|
||||
|
||||
SVFNCHAR STA PRIMFNBF,Y ;(Y)=OFFSET FRM PRIMARY NAME BUF.
|
||||
INY
|
||||
CPY #60 ;TOTAL OF 60 CHARS IN BOTH BUFS.
|
||||
BCC NCHR2ETC ;HAVEN'T HIT ",", EOL MARKER (IE.
|
||||
;<CR>) OR DONE ALL 60 CHARS YET.
|
||||
|
||||
* DONE ALL 60 CHARS SO IGNORE REST
|
||||
* OF CHARS UNTIL GET "," OR <CR>.
|
||||
|
||||
PURGEFN JSR CMDCHAR ;GET NEXT CHAR.
|
||||
BNE PURGEFN ;NOT $00 YET SO GO GET NXT CHAR.
|
||||
|
||||
* JUST FINISHED NAME, SO CHK IF IT
|
||||
* WAS FIRST OR SECOND FILENAME.
|
||||
|
||||
DONEFN PLP ;RETRIEVE STATUS FROM STACK.
|
||||
BNE CKFN2LGL ;Z-FLAG CLR SO DONE 2ND FILENAME.
|
||||
|
||||
* JUST FINISHED FIRST NAME, SO SEE
|
||||
* IF A SECOND FILENAME IS REQUIRED.
|
||||
* (THAT IS, ARE WE DEALING WITH
|
||||
* THE "RENAME" COMMAND?)
|
||||
|
||||
FINFIRST LDY NDX2CMD ;GET INDEX ASSOC WITH CMD ISSUED.
|
||||
LDA #%00010000 ;CHK BIT 4 OF CMDATTRB TO SEE IF
|
||||
AND CMDATTRB,Y ;2ND NAME REQUIRED (IE RENAME ?).
|
||||
BEQ CKFN1LGL ;2ND NAME NOT APPLICABLE SO GO
|
||||
;& CHK 1RST NAME BUF.
|
||||
|
||||
* SECONDARY FILENAME APPLICABLE SO
|
||||
* DEALING WITH "RENAME" COMMAND.
|
||||
|
||||
LDY #30 ;(Y) = INDEX 2 START OF 2ND NAME.
|
||||
PHP ;PUT STATUS ON STK (Z-FLG = 0) TO
|
||||
BNE FNAMCHR1 ;SIGNAL DEALING WITH 2ND NAME &
|
||||
;GO BACK TO GET ITS CHARS.
|
||||
;ALWAYS TAKE BRANCH.
|
||||
|
||||
* DONE PROCESSING ASSOC WITH SECONDARY
|
||||
* FILENAME SO NOW CHK IF ANY OF THESE
|
||||
* CHARS WERE LEGAL & THERE4 STUCK IN
|
||||
* THE SECONDARY FILENAME BUFFER.
|
||||
|
||||
CKFN2LGL LDA SCNDFNBF ;CHK 1RST BYTE IN SECONDARY.
|
||||
CMP #" " ;IF IT IS A <SPC>, THEN NO CHARS
|
||||
BEQ GOXITDOS ;WERE GOOD & SO A 2ND NAME WAS
|
||||
;REQUIRED BUT NOT ISSUED,SO EXIT.
|
||||
|
||||
* ONLY PRIMARY FILENAME APPLICABLE
|
||||
* SO CHK IF WE GOT ANY CHRS THAT
|
||||
* WERE LEGAL & THERE4 PUT IN THE
|
||||
* PRIMARY FILENAME BUFFER.
|
||||
|
||||
CKFN1LGL LDA PRIMFNBF ;IF 1RST CHAR IN BUF IS A <SPC>,
|
||||
CMP #" " ;A LEGAL PRIMARY FILENAME WAS NOT
|
||||
;ISSUED SO FALL THRU TO SEE IF IT
|
||||
;WAS REQUIRED OR OPTIONAL.
|
||||
BNE DFLTPRSD ;BRANCH IF GOT PRIMARY FILENAME.
|
||||
|
||||
* PRIMARY FILENAME WAS NOT ISSUED
|
||||
* SO CHK IF IT WAS REQUIRED OR OPTIONAL.
|
||||
* (IE. WAS CMD A CLOSE, LOAD, SAVE OR RUN?)
|
||||
|
||||
LDY NDX2CMD ;GET INDEX ASSOC WITH CMD.
|
||||
LDA #%11000000 ;CHK BITS 7 & 6 TO SEE IF A NAME
|
||||
AND CMDATTRB,Y ;IS REQUIRED.
|
||||
BEQ GOXITDOS ;A PRIMARY NAME IS REQUIRED BUT
|
||||
;WAS NOT ISSUED, SO GO EXIT DOS.
|
||||
|
||||
* WAS COMMAND A "CLOSE"?
|
||||
|
||||
BPL DFLTPRSD ;NAME WASN'T PRESENT, BUT IS NO
|
||||
;BIG DEAL CAUSE IT WAS OPTIONAL.
|
||||
GOXITDOS JMP CKIFCTRL ;CMD WAS LOAD, RUN OR SAVE WHICH
|
||||
;CAN ALSO BE BASIC COMMANDS.
|
||||
|
||||
|
||||
*======================================
|
||||
* BLANK OUT BOTH PRIMARY ($AA75-$AA92)
|
||||
* AND SECONDARY ($AA93-$AAB0) FILENAME
|
||||
* BUFFERS.
|
||||
*======================================
|
||||
|
||||
BLNKFNBF LDY #60 ;30 BYTES IN EACH BUFFER.
|
||||
BLNK1RST LDA #" " ;BLANK.
|
||||
STORBLNK STA PRIMFNBF-1,Y
|
||||
DEY
|
||||
BNE STORBLNK ;MORE BYTES TO BLANK OUT.
|
||||
RTS
|
||||
|
||||
|
||||
*===================================
|
||||
* FILENAME NOT APPLICABLE TO COMMAND
|
||||
* (EX. CATALOG, MON, NOMON, FP, INT,
|
||||
* PR#, IN# OR MAXFILES).
|
||||
*===================================
|
||||
|
||||
FNOTAPPL STA PRIMFNBF ;PUT A $00 IN THE FIRST BYTE OF
|
||||
;THE PRIMARY FILENAME BUFFER.
|
||||
;************* NOTE *************
|
||||
;* ALTHOUGH THIS SEEMS LIKE A *
|
||||
;* BEGNIN INSTRUCTION, IT IS *
|
||||
;* IMPORTANT BECAUSE IT IS LATER*
|
||||
;* USED 2 INSURE THAT A MATCHING*
|
||||
;* DOS FILENAME BUF WON'T BE *
|
||||
;* FOUND WHEN THE GETBUFF ROUT'N*
|
||||
;* ($A764) IS EVENTUALLY USED BY*
|
||||
;* THE VARIOUS DOS CMDS. AS A *
|
||||
;* RESULT, THE HIGHEST NUMBERED *
|
||||
;* (LOWEST IN MEMORY) FREE DOS *
|
||||
;* FILENAME BUFFER WILL BE *
|
||||
;* SELECTED. *
|
||||
;********************************
|
||||
|
||||
* COMMAND DIDN'T REQUIRE A FILENAME
|
||||
* SO NOW CHK & SEE IF IT EXPECTS ANY
|
||||
* NUMERIC ARGUMENTS. (IE. WAS IT PR#,
|
||||
* IN# OR MAXFILES CMD?)
|
||||
|
||||
LDA #%00001100 ;TEST BITS 2 & 3 TO SEE IF IN#,
|
||||
AND CMDATTRB,Y ;PR# OR MAXFILES NUMERIC
|
||||
;OPERAND IS EXPECTED.
|
||||
BEQ DFLTPRSD ;BRANCH IF NOT EXPECTED.
|
||||
|
||||
* IN#,PR# OR MAXFILES NUMERIC
|
||||
* OPERAND EXPECTED.
|
||||
|
||||
INPRMAX JSR CNVRTASC ;CONVERT ASCII NUMBER ARGUMENT TO
|
||||
;HEX WITH RESULT IN A5L/H.
|
||||
BCS TOSYNTX ;CHR NOT #, EXIT WITH SYNTAX ERR.
|
||||
TAY ;(Y) = HI BYTE OF CONVERTED CHAR.
|
||||
BNE ARGRNGER ;RANGE ERROR - CAUSE VALUE > 255.
|
||||
CPX #17
|
||||
BCS ARGRNGER ;RANGE ERROR CAUSE IF MAXFILES OR
|
||||
;IN# OR PR# ARGUMENT > 16, THEN
|
||||
;VALUE TOO LARGE.
|
||||
|
||||
* WAS COMMAND A PR# OR IN#?
|
||||
|
||||
LDY NDX2CMD ;CHK TO SEE IF A SLOT VALUE IS
|
||||
LDA #%00001000 ;APPLICABLE TO THE COMMAND.
|
||||
AND CMDATTRB,Y
|
||||
BEQ MAXFMIN ;SLOT VAL NOT APPLICABLE SO MUST
|
||||
;BE DEALING WITH MAXFILES.
|
||||
|
||||
* COMMAND WAS PR# OR IN# SO NOW CHECK
|
||||
* IF SLOT VALUE IS TOO LARGE OR NOT.
|
||||
* (LEGAL RANGE IS 0 TO 7.)
|
||||
|
||||
CPX #8 ;TOO LARGE?
|
||||
BCS GOXITDOS ;YES -BAIL OUT.
|
||||
BCC DFLTPRSD ;NO -SET DFLTS & CONTINUE PARSING
|
||||
|
||||
* CHECK MINIMUM VALUE FOR MAXFILES.
|
||||
* (LEGAL RANGE IS 1 TO 16.)
|
||||
|
||||
MAXFMIN TXA
|
||||
BNE DFLTPRSD ;NOT 0, SO OKAY.
|
||||
|
||||
* ARGUMENT FOR MAXFILES, SLOT, IN#
|
||||
* OR PR# WERE ILLEGAL.
|
||||
|
||||
ARGRNGER LDA #2 ;SET RETURN CODE FOR RANGE ERROR.
|
||||
JMP ERRHNDLR ;GO HANDLE THE ERROR.
|
||||
|
||||
TOSYNTX JMP SYNTXERR ;EXIT VIA SYNTAX ERROR.
|
||||
|
||||
* INITIALIZE CUMLOPTN & PARSED TABLE.
|
||||
|
||||
DFLTPRSD LDA #0
|
||||
STA CUMLOPTN ;SET CUMLOPTN TO DEFAULT VAL OF 0
|
||||
;TO ASSUME NO OPTIONS ISSUED.
|
||||
STA MONPRSD ;SET DEFAULT VALS IN PARSED TBL.
|
||||
STA VOLPRSD ;THAT IS ASSUME THAT:
|
||||
STA LENPRSD ; - C, I, O WEREN'T ISSUED.
|
||||
STA LENPRSD+1 ; - VOL # AND LENGTH ARE 0.
|
||||
JSR ZEROPTCH ;SET TEMPBYT & BYTPRSD TO 0 DFLTS
|
||||
LDA NDX2INBF ;IRREL, MIGHT AS WELL BE 3 "NOP"S
|
||||
;(MADE OBSOLETE BY ZEROPTCH).
|
||||
|
||||
* DO MORE PARSING OF COMMAND LINE.
|
||||
* (IGNORE ANY COMMAS OR SPACES.)
|
||||
|
||||
NXCMDCHR JSR PURGECMD ;GET NEXT CHAR.
|
||||
BNE CHKOPTNS ;IF IT ISN'T A <CR> OR COMMA THEN
|
||||
;MAYBE ITS AN OPTION, SO TAKE
|
||||
;BRANCH TO CHECK IT OUT.
|
||||
CMP #$8D ;WAS IT A <CR>?
|
||||
BNE NXCMDCHR ;NO - SO MUST HAVE BEEN A COMMA.
|
||||
;BRANCH BACK TO IGNORE COMMAS.
|
||||
|
||||
* GOT A <CR> (IE. EOL MARKER), SO NOW
|
||||
* DONE PARSING & MUST MAKE SURE THAT
|
||||
* THE CUMMULATIVE RECORD OF THE OPTIONS
|
||||
* WE ENCOUNTERED IS APPLICABLE TO THE CMD.
|
||||
|
||||
LDX NDX2CMD
|
||||
LDA CUMLOPTN ;CHK IF OPTIONS ARE LEGAL.
|
||||
ORA CMDATTRB+1,X
|
||||
EOR CMDATTRB+1,X
|
||||
BNE GOXITDOS ;ILLEGAL SO EXIT.
|
||||
|
||||
* CUMMULATIVE RECORD OF OPTIONS CAN
|
||||
* LEGALLY BE ASSOCIATED WITH COMMAND.
|
||||
|
||||
LDX TEMPBYT ;TEMPBYT = 0 AS SET IN ZEROPTCH.
|
||||
BEQ TODOSCMD ;ALWAYS.
|
||||
|
||||
* MEANINGLESS INSTRUCTIONS (MADE
|
||||
* OBSOLETE BY INCLUSION OF ZEROPTCH).
|
||||
|
||||
STA TEMPBYT
|
||||
STX NDX2INBF
|
||||
BNE NXCMDCHR
|
||||
|
||||
* CHECK IF CHAR IS AN OPTION.
|
||||
* (IE. A, B, R, L, S, D, V, C, I, O.)
|
||||
|
||||
CHKOPTNS LDX #10
|
||||
CKNXOPTN CMP OPTNTXT-1,X
|
||||
BEQ OPTNOK ;FOUND AN OPTION.
|
||||
DEX
|
||||
BNE CKNXOPTN ;HAVEN'T CHKD ALL OPTIONS YET.
|
||||
|
||||
TOTOSYNT BEQ TOSYNTX ;COULDN'T FIND A MATCH.
|
||||
;(SYNTAX ERR - CHAR NOT OPTION.)
|
||||
|
||||
* GOT AN OPTION SO CHK IF IT WAS
|
||||
* "C", "I" OR "O". (IE. IS A
|
||||
* NUMERIC ARGUMENT EXPECTED?)
|
||||
|
||||
OPTNOK LDA OPTNISSD-1,X
|
||||
BMI CIOPTNS ;IF HI BIT=0, THEN OPTION WAS A
|
||||
;"C", "I" OR "O" AND NO NUMERIC
|
||||
;ARGUMENT IS NEEDED.
|
||||
|
||||
* UPDATE CUMLOPTN TO REFLECT
|
||||
* THE LATEST OPTION.
|
||||
|
||||
ORA CUMLOPTN
|
||||
STA CUMLOPTN
|
||||
|
||||
* NOW CHK IF NUMERIC ARGUMENT THAT
|
||||
* WAS ISSUED WITH OPTION IS LEGAL.
|
||||
|
||||
DEX ;REDUCE COUNTER THAT WAS KICKED UP
|
||||
;IN ANTICIPATION OF MORE CHARS
|
||||
;IN THE CMDCHAR ROUTINE.
|
||||
STX NDX2OPTN ;SAVE INDEX TO OPTION.
|
||||
JSR CNVRTASC ;CONVERT ASCII # TO HEX.
|
||||
|
||||
* WAS IT A NUMERIC CHARACTER?
|
||||
|
||||
BCS TOSYNTX ;NO - SYNTAX ERROR.
|
||||
|
||||
* CHARACTER WAS NUMERIC.
|
||||
|
||||
LDA NDX2OPTN ;RETRIEVE INDEX TO OPTION.
|
||||
ASL ;TIMES 4 CAUSE GOING TO CHK MIN
|
||||
ASL ;& MAX VALS OF LEGAL RANGES ASSOC
|
||||
;WITH OPTION (2 BYTES @).
|
||||
TAY ;(Y) = INDEX TO LEGAL RANGE TBL.
|
||||
|
||||
* CHECK IF ARGUMENT IS TOO LARGE.
|
||||
|
||||
LDA A5L+1 ;GET HI BYTE OF ARGUMENT.
|
||||
BNE CKMAXVAL ;BRANCH IF NOT 0.
|
||||
LDA A5L ;HI BYTE WAS 0 SO CHK LOW BYTE.
|
||||
CMP OPTNRNG,Y
|
||||
BCC ARGRNGER ;RANGE ERR -ARGUMENT < MIN LEGAL.
|
||||
|
||||
* CHECK IF ARGUMENT < = MAX LEGAL PLUS 1.
|
||||
|
||||
LDA A5L+1
|
||||
CKMAXVAL CMP OPTNRNG+3,Y ;CMP HI BYTE TO MAX LEGAL VAL.
|
||||
BCC SVALOPTN ;LESS THAN MAX SO ARGUMENT OK.
|
||||
TOARGRNG BNE ARGRNGER ;ARGUMENT > MAX LGL, SO RNG ERR.
|
||||
LDA A5L ;NOW CHK IF LOW BYTE OF ARGUMENT
|
||||
CMP OPTNRNG+2,Y ;COMPLIES TO MAX LEGAL LOW BYTE.
|
||||
BCC SVALOPTN ;ARGUMENT IS LEGAL.
|
||||
BNE TOARGRNG ;ARGUMENT IS ILLEGAL.
|
||||
|
||||
* SAVE THE OPTION VALUE IN THE PARSED TABLE.
|
||||
|
||||
SVALOPTN LDA TEMPBYT ;OBSOLETE, TEMPBYT WAS SET TO 0
|
||||
BNE NXCMDCHR ;IN ZEROPTCH SO ALWAYS FALL THRU.
|
||||
TYA ;(Y)-->(A)=INDEX TO OPTION RNGS.
|
||||
LSR ;DIVIDE BY 2 CAUSE @ OPTION RANGE
|
||||
;TABLE HAS 4 BYTES, BUT @ PARSED
|
||||
;VAL ENTRY IS ONLY 2 BYTES LONG.
|
||||
TAY ;PUT INDEX 2 PARSED TABLE IN (Y).
|
||||
LDA A5L+1 ;STORE ARGUMENT IN PARSED TBL.
|
||||
STA VOLPRSD+1,Y
|
||||
LDA A5L
|
||||
STA VOLPRSD,Y
|
||||
|
||||
* GO SEE IF ANY MORE OPTIONS ARE
|
||||
* PRESENT ON THE COMMAND LINE.
|
||||
|
||||
TONXOPTN JMP NXCMDCHR
|
||||
|
||||
* OPTION WAS A "C", "I" OR "O".
|
||||
|
||||
CIOPTNS PHA ;PUT (A) = OPTNISSD ON STK.
|
||||
LDA #%10000000 ;UPDATE CUMLOPTN TO SIGNAL THAT
|
||||
ORA CUMLOPTN ;"C", "I" OR "O" OPTIONS ISSUED.
|
||||
STA CUMLOPTN
|
||||
PLA ;GET (A) = OPTNISSD BACK FRM STK.
|
||||
AND #%01111111 ;TURN HI BIT OFF.
|
||||
ORA MONPRSD ;UPDATE MONPRSD IN PARSED TABLE.
|
||||
STA MONPRSD
|
||||
BNE TONXOPTN ;GO SEE IF ANY MORE OPTIONS.
|
||||
BEQ TOTOSYNT ;IRRELEVANT.
|
||||
|
||||
|
||||
*=================================
|
||||
* FINAL PROCESSING OF DOS COMMAND.
|
||||
*=================================
|
||||
|
||||
TODOSCMD JSR DODOSCMD ;GO DO THE DOS COMMAND.
|
||||
|
||||
|
||||
*---------------------------------------*
|
||||
* *
|
||||
* - MOST, BUT NOT ALL, DOS CMDS RTN HERE. *
|
||||
* - IF AN ERROR IS ENCOUNTERED, EXECUTION *
|
||||
* EXITS DOS'S ERROR HANDLER VIA RESTART *
|
||||
* ($D43C) OR BASIC'S ERROR-HANDLING *
|
||||
* ROUTINE (BSCERHLR, $D865). *
|
||||
* - FP EXITS BACK INTO DOS'S COLDSTART *
|
||||
* ROUTINE (DOSCOLD, $9D84). *
|
||||
* - INT & CHAIN GO INTO INTEGER BASIC IF *
|
||||
* THE INTEGER LANGUAGE IS AVAILABLE. *
|
||||
* - THE WRITE & READ CMDS RETURN TO THE *
|
||||
* FINSHCMD ROUTINE ($9F83) SHOWN BELOW. *
|
||||
* - BLOAD RTNS TO AFTRCMD IF IT WAS NOT *
|
||||
* CALLED BY THE BRUN CMD. OTHERWISE, *
|
||||
* BLOAD RTNS TO THE BRUN CMD HNDLR AT *
|
||||
* $A391. *
|
||||
* - BRUN EXECUTES THE BINARY FILE BEFORE *
|
||||
* RETURNING. IF THE BRUNED PGM PERFORMED*
|
||||
* ANY INPUT OR OUTPUT, OR IF THE BINARY *
|
||||
* FILE WAS BRUN WITH MON IN EFFECT, THE *
|
||||
* PRGM GETS HUNG UP IN AN ININITE LOOP. *
|
||||
* (SEE FORMATTED DISASSEMBLY OF THE CMD *
|
||||
* PARSING & PROCESSING ROUTINES FOR *
|
||||
* FURTHER DETAILS.)
|
||||
* - THE LOAD CMD GOES INTO APPLESOFT (AT *
|
||||
* $D4F2) TO RESET THE PRGM LINK PTRS *
|
||||
* AND THEN GOES ON TO THE RESTART *
|
||||
* ROUTINE ($D43C). IF THE LOAD CMD WAS *
|
||||
* CALLED FROM A RUN, EXECUTION JUMPS *
|
||||
* BACK INTO THE RUN CMD HNDLR AT *
|
||||
* RUNFPINT ($A4DC). *
|
||||
* - THE RUN CMD EXITS INTO APPLESOFT AT *
|
||||
* STKINI ($D683) & EVENTUALLY RTNS TO *
|
||||
* THE RESTART ROUTINE ($D43C). *
|
||||
* *
|
||||
*-----------------------------------------*
|
||||
|
||||
AFTRCMD JMP FINSHCMD
|
||||
|
||||
|
||||
|
||||
*=================================
|
||||
* DO THE DOS COMMAND.
|
||||
*=================================
|
||||
|
||||
DODOSCMD JSR RESTAT0 ;RESET CONDITION TO 0. THAT IS,
|
||||
;SET CONDNFLG AND OPUTCOND = 0.
|
||||
JSR CLRFMPRM ;CLEAR OUT THE FM PARAMETER LIST
|
||||
;SO WE CAN CUSTOMIZE IT IN
|
||||
;ACCORDANCE WITH THE SPECIFIC DOS
|
||||
;COMMAND HANDLER CALLED.
|
||||
LDA NDX2CMD ;GET (A) = INDEX TO COMMAND.
|
||||
TAX ;(X) = INDEX 2 TBL OF ENTRY PTS.
|
||||
LDA CMDTBL+1,X ;GET ADR-1 OF THE CMD'S ROUTINE &
|
||||
PHA ;PUT IT ON STACK (HI BYTE 1RST).
|
||||
LDA CMDTBL,X
|
||||
PHA
|
||||
RTS ;DO A "STK JMP" TO PROCESS CMD.
|
||||
|
||||
|
||||
*=================================
|
||||
* GET CHAR FROM INPUT BUFFER, SET
|
||||
* Z-FLAG IF <CR> OR COMMA.
|
||||
*=================================
|
||||
|
||||
CMDCHAR LDX NDX2INBF ;(X) = INDEX TO INPUT BUFFER.
|
||||
LDA BUF200,X ;GET NEXT CHAR.
|
||||
CMP #$8D ;IS IT A <CR>?
|
||||
BEQ CMDCHRTS ;YES.
|
||||
INX ;(X)=INDEX 4 NXT ANTICIPATED CHR.
|
||||
STX NDX2INBF
|
||||
CMP #"," ;COMMA?
|
||||
CMDCHRTS RTS ;EXIT WITH Z-FLAG CONDITIONED.
|
||||
;Z=1 IF CHAR IS A <CR> OR COMMA.
|
||||
|
||||
|
||||
*========================================
|
||||
* GET 1RST NON-SPACE CHAR FROM INPUT BUF.
|
||||
* SET Z-FLAG IF IT IS <CR> OR ",".
|
||||
*========================================
|
||||
|
||||
PURGECMD JSR CMDCHAR ;GET 1RST CHAR.
|
||||
BEQ CMDCHRTS ;EXIT IF <CR> OR COMMA.
|
||||
CMP #" " ;SPACE?
|
||||
BEQ PURGECMD ;YES - IGNORE LEADING SPACES.
|
||||
RTS
|
||||
|
||||
|
||||
*=================================
|
||||
* CLEAR OUT THE FM PARAMETER LIST.
|
||||
* - SO WE CAN CUSTOMIZE IT IN
|
||||
* ACCORANCE WITH THE SPECIFIC
|
||||
* DOS COMMAND HANDLER CALLED.
|
||||
*=================================
|
||||
|
||||
CLRFMPRM LDA #0
|
||||
LDY #$16 ;22 BYTES TO ZERO OUT.
|
||||
ZFMPARM STA FMPRMLST-1,Y ;STORE ZERO BYTE.
|
||||
DEY ;$16 --> $01, EXIT AT $00.
|
||||
BNE ZFMPARM
|
||||
RTS
|
||||
|
||||
|
||||
*======================================
|
||||
* CONVERT ASCII TO HEX OR DEC.
|
||||
* ON ENTRY: NDX2INBF INDEXES INPUT BUF.
|
||||
* ON EXIT: A5L/H AND (X,A) = LOW/HI
|
||||
* BYTES OF RESULT.
|
||||
* (C) = 0 = GOOD CONVERSION.
|
||||
* (C) = 1 = INVALID CHARS.
|
||||
*======================================
|
||||
|
||||
CNVRTASC LDA #0 ;ZERO OUT LOC'S TO HOLD RESULT.
|
||||
STA A5L ;LOW BYTE OF RESULT.
|
||||
STA A5L+1 ;HI BYTE OF RESULT.
|
||||
JSR PURGECMD ;GET 1RST NON-SPACE CHAR.
|
||||
PHP ;SAVE STATUS (Z-FLAG) ON STK.
|
||||
;(IF <CR> OR COMMA, Z-FLAG = 1.)
|
||||
|
||||
* CHK TO SEE IF WANT TO CONVERT
|
||||
* ASCII TO HEX OR ASCII TO DEC.
|
||||
|
||||
CMP #"$" ;IS HEX SYMBOL PRESENT?
|
||||
BEQ ASC2HEX ;YES - BRANCH FOR ASCII TO HEX.
|
||||
|
||||
|
||||
*--------------------------------
|
||||
* ASCII TO DEC CONVERSION WANTED.
|
||||
*--------------------------------
|
||||
|
||||
PLP ;GET STATUS DENOTING IF CR OR ","
|
||||
JMP CKIFDONE ;BEGIN DEC CONVERSION OF 1RST CHR
|
||||
|
||||
ASC2DEC JSR PURGECMD ;GET 2ND & SUBSEQUENT ASCII CHARS
|
||||
;TO BE CONVERTED TO DECIMAL.
|
||||
;(IGNORE SPACES.)
|
||||
|
||||
CKIFDONE BNE SUBTRASC ;BRANCH IF NOT <CR> OR COMMA.
|
||||
;(ALWAYS FALL THRU IF ACCESSED FRM
|
||||
;THE HEX CONVERSION ROUTINE.)
|
||||
|
||||
* SUCCESSFUL CONVERSION - EXIT
|
||||
* WITH A5L/H AND (X,A) CONTAINING
|
||||
* LOW/HI BYTES OF RESULT.
|
||||
|
||||
LDX A5L ;RESULT LOW.
|
||||
LDA A5L+1 ;RESULT HI.
|
||||
CLC ;(C)=0 TO SIGNAL GOOD CONVERSION.
|
||||
RTS ;EXIT TO CALLER OF CNVRTASC.
|
||||
|
||||
* CHECK VALIDITY OF ASCII CHARS FOR
|
||||
* REPRESENTATION OF DECIMAL NUMBERS.
|
||||
|
||||
SUBTRASC SEC
|
||||
SBC #$B0 ;SUBTRACT ASCII "0".
|
||||
BMI NOTASCII ;ERROR CAUSE < 0.
|
||||
CMP #$0A ;DECIMAL 10.
|
||||
BCS NOTASCII ;ERROR CAUSE > 9.
|
||||
|
||||
* MULTIPLY RUNNING RESULT * 10
|
||||
* AND THEN ADD NEW DIGIT.
|
||||
|
||||
JSR DOUBLE ;GET RESULT * 2.
|
||||
ADC A5L
|
||||
TAX ;(X) = LOW RESULT * 2 + NEW DIGIT
|
||||
LDA #0
|
||||
ADC A5L+1 ;ADD (C) TO HI BYTE OF RESULT.
|
||||
TAY ;(Y) = HI BYTE OF RESULT*2 + (C).
|
||||
JSR DOUBLE ;(A) = RESULT * 8.
|
||||
JSR DOUBLE
|
||||
TXA
|
||||
ADC A5L
|
||||
STA A5L ;(RESULT*2+NEW DIGIT)+(RESULT*8).
|
||||
TYA
|
||||
ADC A5L+1 ;ADD (C) TO UPDATE HI BYTE.
|
||||
STA A5L+1
|
||||
BCC ASC2DEC ;BRANCH IF # <65536.
|
||||
|
||||
* ERROR - INVALID ASCII NUMBER.
|
||||
|
||||
NOTASCII SEC ;EXIT WITH (C)=1 TO SIGNAL ERROR.
|
||||
RTS ;RETURN TO CALLER OF CNVRTASC.
|
||||
|
||||
* MULTIPLY 2-BYTE RESULT TIMES 2.
|
||||
|
||||
DOUBLE ASL A5L ;"ROLL" HI & LOW BYTES AS A UNIT.
|
||||
ROL A5L+1 ;(PICK UP (C) IN HI BYTE.)
|
||||
RTS
|
||||
|
||||
|
||||
*---------------------------------
|
||||
* CONVERT ASCII CHARS TO HEX.
|
||||
*---------------------------------
|
||||
|
||||
ASC2HEX PLP ;THROW SAVED STATUS OFF STACK.
|
||||
GETASCII JSR PURGECMD ;GET 1RST & SUBSEQUENT CHARS THAT
|
||||
;OCCUR AFTER THE HEX ("$") SYMBOL
|
||||
BEQ CKIFDONE ;GO EXIT IF <CR> OR COMMA.
|
||||
|
||||
* CHECK VALIDITY OF ASCII CHARS
|
||||
* FOR CONVERSION TO HEX.
|
||||
|
||||
SEC
|
||||
SBC #$B0 ;SUBTRACT ASCII "0".
|
||||
BMI NOTASCII ;ERROR CAUSE < 0.
|
||||
CMP #$0A
|
||||
BCC PRP2DUBL ;VALID: 0 <--> 9.
|
||||
SBC #7 ;CHK HI RANGE OF HEX #'S.
|
||||
BMI NOTASCII ;ERROR CAUSE > $09 AND < $0A.
|
||||
CMP #$10
|
||||
BCS NOTASCII ;ERROR CAUSE > $0F.
|
||||
|
||||
* MOVE RESULT IN A5L/H UP A NIBBLE
|
||||
* BY ROLLING IT AS A UNIT (IE. *16).
|
||||
|
||||
PRP2DUBL LDX #4 ;(X) = # OF TIMES TO DOUBLE UNIT.
|
||||
TIMES2 JSR DOUBLE ;MULTIPLY RESULT * 2.
|
||||
DEX
|
||||
BNE TIMES2 ;MORE MULTIPLICATION TO DO.
|
||||
|
||||
* MERGE HEX REPRESENTATION OF DIGIT
|
||||
* INTO LOW NIBBLE POS'N OF RESULT.
|
||||
*
|
||||
* NOTE BUG: NO CHK IS MADE TO TRAP
|
||||
* NUMBERS > $FFFF. IF TOO MANY #'S
|
||||
* ARE INPUT, ONLY THE LAST 4 DIGITS
|
||||
* ARE REFLECTED IN THE RESULT.
|
||||
|
||||
ORA A5L
|
||||
STA A5L
|
||||
JMP GETASCII ;GO GET NEXT CHAR TO CONVERT.
|
||||
|
||||
|
||||
*==================================
|
||||
* PR# COMMAND HANDLER.
|
||||
*==================================
|
||||
|
||||
* ON ENTRY, A5L/H CONTAINS THE HEX
|
||||
* VALUE OF THE ARGUMENT (SLOT #)
|
||||
* THAT WAS ISSUED WITH THE CMD.
|
||||
* THE ARGUMENT WAS PREVIOUSLY
|
||||
* SCREENED BY THE INPRMAX ($A0AA)
|
||||
* ROUTINE. IF SLOT# = 0, THEN THE
|
||||
* OUTPUT HOOK (CSW) POINTS 2 COUT1
|
||||
* ($FDF0). OTHERWISE, CSW POINTS
|
||||
* TO $CS00 (WHERE S = SLOT #).
|
||||
|
||||
CMDPR LDA A5L ;GET SLOT NUMBER.
|
||||
JMP OUTPORT ;USE MONITOR ROM 2 SET OUTPUT HK.
|
||||
;RTN 2 THE CALLER OF THE PR# CMD.
|
||||
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
|
||||
;ASSOCIATED WITH THE COMMAND
|
||||
;PARSING & PROCESSING ROUTINES.)
|
||||
|
||||
|
||||
*=================================
|
||||
* THE IN# COMMAND HANDLER.
|
||||
*=================================
|
||||
|
||||
* ON ENTRY, A5L/H CONTAINS THE HEX
|
||||
* VALUE OF THE ARGUMENT (SLOT #)
|
||||
* THAT WAS ISSUED WITH THE CMD.
|
||||
* THE ARGUMENT WAS PREVIOUSLY
|
||||
* SCREENED BY THE INPRMAX ($A0AA)
|
||||
* ROUTINE. IF SLOT# = 0, THEN THE
|
||||
* INPUT HOOK (KSW) POINTS TO KEYIN
|
||||
* ($FD1B). OTHERWISE, KSW POINTS
|
||||
* TO $CS00 (WHERE S = SLOT #).
|
||||
|
||||
CMDIN LDA A5L ;GET SLOT NUMBER.
|
||||
JMP INPORT ;USE MONITOR ROM TO SET INPUT HK.
|
||||
;RTN 2 THE CALLER OF THE IN# CMD.
|
||||
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
|
||||
;ASSOCIATED WITH THE COMMAND
|
||||
;PARSING & PROCESSING ROUTINES.)
|
||||
|