1
0
mirror of https://github.com/opsxcq/mirror-textfiles.com.git synced 2025-08-08 13:16:27 +02:00
This commit is contained in:
OPSXCQ
2017-11-23 18:01:42 -03:00
parent 8441bbc5a3
commit 1bb7f62fa0
54 changed files with 38598 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View 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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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).)

View 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).)

View 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).)

View 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).)

View 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).

File diff suppressed because it is too large Load Diff

View 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).)

View 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).)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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.

File diff suppressed because it is too large Load Diff

View 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
============

File diff suppressed because it is too large Load Diff

View 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).)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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.

View 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.)
{

View File

@@ -0,0 +1,870 @@
*======================================
* THE MON AND NOMON COMMAND HANDLERS.
*======================================
* NOTE: THE MON & NOMON COMMANDS AND
* THEIR ALPHABETIC ARGUMENTS (C,I,O)
* ARE FIRST DETECTED VIA COMMAND
* PARSING. CIOCUMUL IS TESTED AT THE
* DSPLYCHR ($9F9F) PORTION OF THE VIDEO
* PARSING ROUTINE TO SEE IF A CHAR
* SHOULD BE SENT TO THE SCREEN OR
* NOT. IT IS EASY TO BECOME CONFUSED
* OVER THE DISTINCTION BETWEEN
* CIOCUMUL AND MONPRSD. THE FORMER
* REPRESENTS THE CUMMULATIVE UPDATED
* RECORD OF THE C, I, O ARGUMENTS
* WHEREAS THE LATER DESCRIBES THE
* MOST RECENT ADDITIONS OF THE
* C, I, O ARGUMENTS PRESENT IN THE
* TABLE OF PARSED VALUES.
* THE ALPHABETIC ARUMENTS (C, I, O)
* ARE REPRESENTED BY THE FOLLOWING
* SPECIFIC BITS:
* C = $40 = %01000000
* I = $20 = %00100000
* O = $10 = %00010000
* COMBINATION OF ARGUMENTS ARE SIMPLY
* DESCRIBED BY THE APPROPRIATE BIT
* SETTINGS: EX. CIO = $70 = $01110000
CMDMON LDA CIOCUMUL ;GET PREV CUMMULATIVE RECORD AND
ORA MONPRSD ;MERGE WITH THE LATEST PARSED VAL
STA CIOCUMUL ;TO UPDATE CUMMULATIVE RECORD.
RTS ;RTN 2 THE CALLER OF THE MON CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
CMDNOMON BIT MONPRSD ;TEST BIT6 IN PARSED TBL TO SEE IF
;"NOMON C" IS SELECTED.
BVC CLRMON ;BRANCH IF "C" NOT INCLUDED.
JSR CRVIADOS ;"C" WAS INCLUDED, SO PRT <CR>
;CAUSE CMD (BUT NOT <CR>) WAS
;ALREADY PRINTED.
CLRMON LDA #%01110000 ;SHUT OFF BITS IN PARSED TABLE
EOR MONPRSD ;THAT CORRESPOND 2 THE ALPHABETIC
;ARGUMENTS ISSUED WITH NOMON CMD.
AND CIOCUMUL ;NOW MAKE SURE THAT THOSE BITS
STA CIOCUMUL ;ARE OFF IN CUMMULATIVE RECORD.
RTS ;RTN TO CALLER OF THE NOMON CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*==================================
* THE MAXFILES COMMAND HANDLER.
*==================================
* THE MAXFILES COMMAND IS USED TO
* DEFINE THE # OF FILES THAT MAY
* BE OPENED AT ONE TIME (IE. 1-16).
* A DEFAULT VALUE OF 3 IS USED FOR
* COLDSTARTS (IE, WHEN THE DISK IS
* BOOTED) OR WHEN THE FP OR INT
* COMMANDS ARE ISSUED. THIS VALUE
* CAN BE CHANGED BY ALTERING THE
* CONTENTS OF $AAB1. (THE MAXFILES
* CMD CAN BE TRICKED INTO BUILDING
* ITS BUFFERS AT A LOWER LOCATION
* IN ORDER TO CREATE A SANCTUARY
* WHERE CUSTOM MACHINE LANGUAGE
* ROUTINES CAN'T BE OVERWRITTEN BY
* BASIC. SEE FORMATTED DIS'MBLY
* OF MAXFILES CMD FOR DETAILS.)
CMDMXFIL LDA #0 ;SHUT OFF THE EXEC FLG.
STA EXECFLAG
LDA A5L ;GET ARGUMENT ISSUED WITH CMD AND
PHA ;SAVE IT ON THE STK.
;NOTE: ARGUMENT WAS PREVIOUSLY
;SCREENED TO INSURE THAT IS IS
;BTWN 1 AND 16 ($A0AA - $A0C7).
JSR CLOSEALL ;CLOSE ALL OPEN FILES.
PLA ;RETRIEVE ARGUEMENT ISSUED WITH
STA MXFILVAL ;CMD & STORE IT IN THE MAIN
;VARIABLES TABLE.
JMP BILDBUFS ;GO BUILD MXFILVAL # OF DOS BUFS.
;RTNS 2 CALLER OF MAXFILES CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*=================================
* THE DELETE COMMAND HANDLER.
*=================================
CMDELETE LDA #5 ;OPCODE FOR DELETE.
JSR HNDLCMD1 ;CLOSE THE FILE & RLEASE ITS BUF.
;REASSIGN A DOS BUF TO THE FILE.
;CHNG FILE DESCRP IN DIR SEC BUF.
;WRITE UPDATED DIR SEC BUF 2 DSK.
;FREE UP DATA & T/S LIST SECTORS.
;WRITE UPDATED VTOC TO DISK.
JSR GETBUFF ;FIND REASSIGNED DOS BUF.
LDY #0 ;FREE UP DOS BUF OF FILE BY
TYA ;STORING A $00 IN 1RST BYTE OF
STA (A3L),Y ;THE DOS FILE NAME BUFFER.
RTS ;EXIT 2 CALLER OF THE DELETE CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*==================================
* THE LOCK AND UNLOCK CMD HANDLERS.
*==================================
CMDLOCK LDA #7 ;LOCK OPCODE.
BNE LOKUNLOK ;ALWAYS.
CMDUNLOK LDA #8 ;UNLOCK OPCODE.
*---------------------------------
* ROUTINE COMMON TO LOCK, UNLOCK
* AND VERIFY COMMAND HANDLERS.
*---------------------------------
LOKUNLOK JSR HNDLCMD1 ;CALL PART OF THE MAIN COMMAND
;HANDLER ROUTINE TO LOCK, UNLOCK
;OR VERIFY THE FILE.
JMP CMDCLOSE ;EXIT COMMAND VIA CLOSE.
;RTN 2 THE CALLER OF THE COMMAND.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*=================================
* THE VERIFY COMMAND HANDLER.
*=================================
CMDVERFY LDA #12 ;VERIFY OPCODE.
BNE LOKUNLOK ;GO CALL THE CMD HNDLR TO VERIFY
;FILE & THEN EXIT VIA CLOSE CMD.
*=================================
* THE RENAME COMMAND HANDLER.
*=================================
CMDRENAM LDA ADRSFNBF ;COPY ADR OF SECONDARY FILENAME 2
STA RENAMBUF ;RENAME BUF IN FM PARAMETER LIST.
LDA ADRSFNBF+1
STA RENAMBUF+1
LDA #9 ;RENAME OPCODE.
STA TEMPBYT
JSR CLOSIFOP ;CLOSE FILE IF IT IS ALREADY OPEN
;AND THEN DO THE RENAME FUNCTION:
; -COPY NEW FILE NAME 2 DIRECTORY
; SECTOR BUFFER & THEN WRITE THE
; UPDATED DIREC SEC BACK 2 DISK.
JMP CMDCLOSE ;EXIT RENAME CMD VIA CLOSE CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*=================================
* THE APPEND COMMAND HANDLER.
*=================================
CMDAPPND JSR CMDOPEN ;GO OPEN THE FILE TO BE APPENDED.
READ2END JSR RDTXTBYT ;GO READ A TEXT FILE BYTE. (USE
;THE READ FUNCTION AND READ-ONE-
;BYTE SUBFUNCTION.)
BNE READ2END ;TAKE BRANCH IF DEALING WITH A
;VALID (IE. NON-ZERO) DATA BYTE.
;HAVEN'T ENCOUNTERED AN END-OF-
;FILE MARKER ($00) YET,SO GO BACK
;TO READ THE REST OF THE FILE.
JMP CKAPFLG ;FOUND END OF FILE,SO NOW GO BACK
;UP THE FILE POINTER IF NECESSARY
;AND EVENTUALLY EXIT THE APPEND
;CMD HANDLER VIA RSETPTRS ($B6B3)
;AND FMEXIT ($B386). NOTE THAT
;RSETPTRS RESETS THE SAVED STACK
;POINTER (STKSAV, $B39B) SO WE
;EVENTUALLY RETURN TO THE CALLER
;OF THE APPEND COMMAND. EXECUTION
;OFTEN RETURNS TO AFTRCMD ($A17D)
;LOCATED IN THE COMMAND PARSING
;AND PROCESSING ROUTINES.
*=================================
* THE OPEN COMMAND HANDLER.
*=================================
CMDOPEN LDA #0 ;CODE FOR TEXT FILE.
JMP OPNCKTYP ;GO OPEN THE FILE & CHK ITS TYPE.
;RTN 2 THE CALLER OF THE OPEN CMD
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;ASSOCIATED WITH THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*====================================
* COMMON FILE MANAGER CMD HNDLR CODE.
*====================================
HNDLCMD LDA #1 ;OPEN OPCODE.
HNDLCMD1 STA TEMPBYT ;STORE OPCODE IN TEMPBYT.
LDA LENPRSD ;GET L-PARAMETER FROM PARSED TBL.
BNE SAVLENFM ;CHECK IF A NON-ZERO L-PARM WAS
;ISSUED WITH THE COMMAND.
LDA LENPRSD+1
BNE SAVLENFM
LDA #1 ;LNGTH WAS 0 SO MAKE IT 1 INSTEAD
STA LENPRSD
SAVLENFM LDA LENPRSD ;PUT LENGTH IN FM PARAMETER LIST.
STA RECLENFM ;NOTE: RECORD LENGTH = 1 FOR
LDA LENPRSD+1 ;SEQUENTIAL FILES, ELSE PARSED
STA RECLENFM+1 ;LENGTH FOR RANDOM ACCESS FILES.
*----------------------------------
* CLOSE FILE IF IT IS ALREADY OPEN.
*----------------------------------
CLOSIFOP JSR CMDCLOSE ;CLOSE IF ALREADY OPEN.
LDA A5L+1 ;A5L/H POINTS AT HIGHEST NUMBERED
;(LOWEST IN MEMORY) FREE DOS BUF.
BNE SAVFNPTR ;BRANCH IF FOUND A FREE BUFFER.
JMP NOBUFERR ;COULDN'T LOCATE A FREE BUFFER SO
;GO ISSUE OUT OF BUF'S MSG.
SAVFNPTR STA A3L+1 ;RESET A3L/H TO POINT AT DOS BUF
LDA A5L ;THAT WILL USE 4 FILENAME FIELD.
STA A3L
JSR CPYPFN ;REASSIGN A DOS BUFFER 2 THE FILE
;WE WANT TO OPEN.
JSR BUFS2PRM ;GET ADDR'S OF THE VARIOUS DOS
;BUFFERS FROM THE CHAIN BUFFER &
;PUT THEM IN THE FM PARM LIST.
JSR CPY2PARM ;PUT VOL, DRV, SLOT & ADDR OF THE
;PRIMARY FILENAME BUFFER IN THE
;FM PARAMETER LIST.
LDA TEMPBYT ;GET OPCODE BACK FROM TEMPBYT AND
STA OPCODEFM ;STICK IT IN THE FM PARM LIST.
JMP FMDRIVER ;USE FILE MANAGER TO DO FUNCTION.
*=================================
* THE CLOSE COMMAND HANDLER.
*=================================
CMDCLOSE LDA PRIMFNBF ;GET 1RST CHR FRM PRMRY NAME BUF.
CMP #" " ;DON'T ALLOW LEADING SPACES.
BEQ CLOSEALL ;LEADING SPC = SIGNAL 2 CLOSE ALL
;FILES. (A CLOSE CMD WAS ISSUED
;WITH NO ACCOMPANYING FILE NAME.)
JSR GETBUFF ;LOCATE A DOS BUFFER WITH SAME
;NAME, ELSE LOCATE A FREE BUFFER.
EVENTXIT BCS CLOSERTS ;EVENTUALLY EXIT VIA THIS ROUTE!!
JSR CLOSEONE ;MATCHING FILENAME WAS FOUND SO
;GO CLOSE THAT FILE.
JMP CMDCLOSE ;GO BACK TO POINT A5L/H AT A FREE
;DOS BUFFER & EXIT VIA EVENTXIT
;($A2F4) AND CLOSERTS ($A330).
*---------------------------------
* CLOSE A SPECIFIC FILE
* (& FREE ITS BUFFER).
*---------------------------------
CLOSEONE JSR CKEXCBUF ;CHK IF CURRENT FILENAME BUFFER
;BELONGS TO AN EXEC FILE.
BNE FREEBUFF ;BRANCH IF NOT EXECING FROM THIS
;PARTICULAR FILE. NOTE, ALWAYS
;TAKE BRANCH IF CLOSEONE ($A2FC)
;IS ACCESSED VIA CLOSEALL ($A316)
LDA #0 ;CLOSING AN EXEC FILE SO SHUT OFF
STA EXECFLAG ;THE EXEC FLAG. NOTE:THIS INSTRUC
;IS NEVER CARRIED OUT IF ACCESSED
;VIA CLOSEALL. (AN ACTIVE EXEC
;FILE WAS ALREADY DETECTED AND
;SKIPPED BY THE "BEQ CHKNXBUF"
;INSTRUCTION AT $A323.)
FREEBUFF LDY #0 ;FREE UP DOS BUF BY POKING A $00
TYA ;IN 1RST BYT OF DOS FILENAME BUF.
STA (A3L),Y
JSR BUFS2PRM ;GET ADDR'S OF THE VARIOUS DOS
;BUFS FROM THE CHAIN BUF & PUT
;THEM IN THE FM PARAMETER LIST.
LDA #2 ;PUT OPCODE FOR CLOSE FUNCTION
STA OPCODEFM ;IN THE FM PARAMETER LIST.
JMP FMDRIVER ;GO TO THE FILE MANAGER DRIVER TO
;DO THE CLOSE FUNCTION.
*---------------------------------------
* CLOSE ALL FILES (EXCEPT AN EXEC FILE).
* ENTER CLOSEALL WHEN IT IS ACCESSED VIA
* A DIRECT CALL OR IF THE FIRST CHAR IN
* THE PRIMAY FILENAME FIELD WAS A SPACE.
*---------------------------------------
CLOSEALL JSR GETFNBF1 ;PUT ADR OF 1RST DOS FILENAME BUF
;(LOCATED IN CHAIN OF DOS BUFS)
;IN THE A3L/H POINTER.
BNE CKIFEXEC ;ALWAYS.
CHKNXBUF JSR GETNXBUF ;GET ADR OF NEXT DOS FILENAME BUF
;FROM DOS CHAIN POINTERS BUFFER
;(OFFSET 37 & 36 BYTES FROM 1RST
;CHR OF PRESENT DOS FILENAME BUF)
BEQ CLOSERTS ;LNK ZEROED OUT -ALL FILES CLOSED
;(EXIT CLOSEALL VIA THIS ROUTE.)
CKIFEXEC JSR CKEXCBUF ;CHK IF CURRENT DOS FILENAME BUF
;BELONGS TO TO AN EXEC FILE.
BEQ CHKNXBUF ;EXEC ACTIVE SO DON'T CLOSE ITS
;BUFFER OUT OR WILL END UP
;IN NEVER-NEVER LAND. AFTER ALL,
;DON'T WANT TO CLOSE BUFFER IF WE
;ARE USING IT 2 EXEC (IE. WOULD
;BE LIKE BURYING SELVES ALIVE)!!
JSR GETFNBY1 ;GET 1RST BYTE IN DOS NAME BUF.
BEQ CHKNXBUF ;THIS FILE IS ALREADY CLOSED SO
;GO BACK TO CLOSE REST OF FILES.
JSR CLOSEONE ;FILE WAS OPEN SO GO CLOSE IT.
JMP CLOSEALL ;GO TO CLOSERTS VIA CLOSEALL!!!
CLOSERTS RTS ;EXIT TO CALLER OF THE CLOSE CMD.
;(OFTEN EXITS TO AFTRCMD ($A17D)
;LOCATED IN THE COMMAND PARSING &
;PROCESSING ROUTINES.)
*=================================
* THE BSAVE COMMAND HANDLER.
*=================================
CMDBSAVE LDA #%00001001 ;TEST BITS0 & 3 OF CUMLOPTN 2 SEE
AND CUMLOPTN ;IF A(DDR) & L(ENGTH) PARAMETERS
CMP #%00001001 ;WERE ISSUED WITH THE BSAVE CMD.
BEQ DOBSAV ;BOTH A- & L-PARMS PRESENT.
JMP CKIFCTRL ;GOT A SYNTAX ERROR.
DOBSAV LDA #4 ;CODE FOR BINARY FILE.
JSR OPNCKTYP ;CLOSE (IF NECESSARY) & THEN OPN.
LDA ADRPRSD+1 ;PREPARE TO WRITE ADDR TO DISK.
LDY ADRPRSD
JSR WRADRLEN ;CALL WRITE-ONE-BYTE SUBFUNCTION
;TWICE TO PUT A(DDR)-PARAMETER IN
;DATA SEC BUF. (NOTE: LEN2RDWR IS
;USED AS A TEMPORAY BUFFER FOR
;FOR DATA TRANSFER.)
LDA LENPRSD+1 ;PREPARE TO WRITE FILE LENGTH.
LDY LENPRSD
JSR WRADRLEN ;CALL WRITE-ONE-BYTE SUFUNCTION 2
;WRITE LENGTH AS THE 3RD & 4TH
;BYTES IN THE DATA SEC BUF.
;(LATER BUF WRITTEN AS 1RST SEC
;OF FILE. LEN2RDWR IS AGAIN USED
;AS A TEMP BUF 4 DATA TRANSFER.)
* NOW PREPARE TO WRITE THE REST
* OF THE BINARY FILE TO THE DISK.
LDA ADRPRSD+1 ;PUT ADDR OF SOURCE BUFFER IN
LDY ADRPRSD ;THE FM PARAMETER LIST.
JMP RDWRANGE ;GO TO WRITE-RANGE ROUTINE TO
;WRITE REST OF FILE TO THE DISK.
;(FILE IS ALSO VERIFIED AND THEN
;EXITED VIA THE CLOSE COMMAND.)
;EXECUTION EVENTUALLY RETURNS TO
;THE CALLER OF THE BSAVE COMMAND.
;OFTEN, RETURNS 2 AFTRCMD ($A17D)
;LOCATED IN THE CMD PARSING AND
;PROCESSING ROUTINES.
*=================================
* BLOAD COMMAND HANDLER
*=================================
CMDBLOAD JSR HNDLCMD ;CALL THE FM COMMAND HANDLER TO
;OPEN THE FILE.
* COMPARE FILE TYPE WANTED
* WITH FILE TYPE FOUND.
LDA #$7F ;STRIP LOCK BIT FROM FILE TYPE
AND FILTYPFM ;FOUND (VIA OPEN FUNCTION).
CMP #4 ;WAS FILE FOUND A BINARY FILE?
BEQ ADR4BLOD ;YES.
JMP TYPMISM ;NO - GO ISSUE FILE-MISMATCH MSG.
* REDUNDANT CODE! CLOSE (IF NECESSARY)
* AND THEN OPEN THE FILE AGAIN.
ADR4BLOD LDA #4 ;CODE FOR BINARY FILE.
JSR OPNCKTYP ;CLOSE & REOPEN FILE.
JSR RDADRLEN ;READ THE BLOAD ADR FROM THE DISK
;INTO LEN2RDWR.
TAX ;X=LOW BYTE OF BLOAD ADR FRM DSK
LDA CUMLOPTN ;CHK CUMLOPTN TO SEE IF AN A(DDR)
AND #%00000001 ;WAS ISSUED WITH THE BLOAD CMD.
BNE LEN4BLOD ;YES -SO IGNORE ADR READ FROM DSK
; & USE THE ACTUAL PARSED
; A-PARAMETER INSTEAD.
STX ADRPRSD ;STORE ADR READ FRM DSK IN PARSED
STY ADRPRSD+1 ;TABLE. (THIS WAY CAN ALWAYS USE
;VAL IN TABLE FOR BLOAD ADR.)
LEN4BLOD JSR RDADRLEN ;READ THE BLOAD LENGTH OFF DSK.
;(PUT RESULTS IN LEN2RDWR.)
LDX ADRPRSD ;SET (X)/(Y) = EITHER ORIG PARSED
LDY ADRPRSD+1 ;A-PARM ADR OR BLOAD ADR FRM DSK.
JMP LODINTFP ;GO READ THE REST OF THE FILE IN.
;EXITS VIA THE CLOSE COMMAND.
;RETURNS TO CALLER OF THE BLOAD
;CMD. (IF BLOAD CMD NOT CALLED BY
;BRUN, THEN OFTEN RTNS TO AFTRCMD
;($A17D) LOCATED IN THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*=================================
* BRUN COMMAND HANDLER
*=================================
CMDBRUN JSR CMDBLOAD ;BLOAD THE PRGM.
JSR INITIOHK ;POINT THE I/O HOOKS AT DOS.
;NOTE: THIS CAN CREATE SOME
;EXOTIC BUGS IF THE BRUNED PRGM
;PRINTS ANY INFO OR IF "MON" IS
;ACTIVE. SEE FORMATTED DIS'MBLY
;OF BRUN CMD FOR EXPLANATION.)
JMP (ADRPRSD) ;BEGIN EXECUTION OF BINARY PRGM.
;EXECUTION NORMALLY RETURNS TO
;AFTRCMD ($A17D) LOCATED IN THE
;CMD PARSING AND PROCESSING
;ROUTINES. ALSO NOTE THAT
;THE COMPUTER MAY HANG ON CERTAIN
;OCCASSIONS. (SEE THE FORMATTED
;DISASSEMBLY OF THE BRUN CMD FOR
;EXPLANATION.)
*=================================
* SAVE COMMAND HANDLER
*=================================
CMDSAVE LDA ACTBSFLG ;CHK WHICH BASIC IS ACTIVE.
BEQ SAVINTGR ;BRANCH IF USING INTEGER.
;INT=$00, A(ROM)=$40, A(RAM)=$80.
LDA PROTFLG ;IF PROTECTION FLAG IS ON (IE. IS
;NEGATIVE), THEN ALL APPLESOFT
;CMDS CAUSE RUN & DOS'S SAVE CMD
;CAUSES A PHONY PROGRAM-TOO-LARGE
;MESSAGE TO BE GENERATED.
BPL SAVAPSFT ;BRANCH IF PROTECTION FLG IS OFF.
JMP TOOLARGE ;PROTECTED!!! - SPIT OUT PHONY
;PROGRAM-TOO-LARGE MESSAGE & XIT.
*---------------------------------
* SAVE AN APPLESOFT FILE
*---------------------------------
SAVAPSFT LDA #2 ;CODE FOR APPLESOFT FILE.
JSR OPNCKTYP ;GO OPEN THE NAMED FILE & CHECK
;ITS TYPE.
SEC ;CALC THE LNGTH OF THE PRGM SO WE
LDA PRGEND ;CAN WRITE IT AS 1RST TWO BYTES:
SBC TXTTAB ; LENGTH = PRGEND - TXTTAB
TAY
LDA PRGEND+1
SBC TXTTAB+1
JSR WRADRLEN ;WRITE THE LENGTH OF THE FP FILE
;BY USING THE WRITE-ONE-BYTE
;SUBFUNCTION TWICE.
* PREPARE TO WRITE REST OF FILE.
LDA TXTTAB+1 ;PRGM START = START OF OUTPUT BUF
LDY TXTTAB
JMP RDWRANGE ;GO TO THE WRITE-RANGE-OF-BYTES
;ROUTINE 2 WRITE THE REST OF FILE
;AND THEN VERIFY IT.
;AFTER VERIFICATION, THE SAVE CMD
;IS EXITED VIA THE CLOSE CMD.
;EXECUTION THEN RETURNS TO CALLER
;OF THE SAVE CMD. (OFTEN RTNS TO
;AFTRCMD ($A17D) LOCATED IN THE
;DOS CMD PARSING AND PROCESSING
;ROUTINES.)
*---------------------------------
* SAVE AN INTEGER FILE
*---------------------------------
SAVINTGR LDA #1 ;CODE FOR INTEGER FILE.
JSR OPNCKTYP ;GO OPEN THE INTEGER FILE.
SEC ;CALC LENGTH OF FILE.
LDA HIMEM
SBC INTPGMST
TAY
LDA HIMEM+1
SBC INTPGMST+1
JSR WRADRLEN ;WRITE LNGTH 2 DSK BY CALLING THE
;WRITE-ONE-BYTE SUBFUNCTION TWICE
LDA INTPGMST+1
LDY INTPGMST
JMP RDWRANGE ;WRITE THE REST OF FILE TO DSK.
*=================================
* OPEN NAMED FILE & CHECK ITS TYPE
*=================================
OPNCKTYP STA FILTYPFM ;PUT CODE FOR FILE TYPE IN THE
PHA ;FM PARAMETER LIST & SAVE ON STK.
;($00=TXT, $01=INT, $02=FP,
;$04=BIN, $08=S-TYPE, $10=RELOC,
;$20=A-TYPE AND $40=B-TYPE.)
JSR HNDLCMD ;USE THE FM CMD HANDLER TO OPEN.
PLA ;PULL THE FILE TYPE CODE FRM STK.
JMP CHKFTYPE ;GO CHK IF TYPE WNTD = TYPE FOUND
*============================================
* WRITE TWO BYTES.
*--------------------------------------------
* CODE WHICH WRITES ADDRESS AND LENGTH VALUES
* TO THE DATA SECTOR BUFFER. (LATER, THE
* DATA SEC BUF IS WRITTEN TO THE DISK.)
* CALLS WRITE-ONE-BYTE SUBFUNCTION TWICE.
* NOTE THAT LEN2RDWR IS USED AS A TEMPORARY
* BUFFER FOR DATA TRANSFER AS SHOWN BELOW:
* - LOW BYTE OF ADR OR LENGTH --> LEN2RDWR
* --> ONEIOBUF --> DATA SECTOR BUFFER.
* - HI BYTE OF ADR OR LENGTH --> LEN2RDWR+1
* --> ONEIOBUF --> DATA SECTOR BUFFER.
*============================================
WRADRLEN STY LEN2RDWR ;PUT LOW BYTE IN FM PARM LIST IN
;CASE THIS IS A L-PARM & WE NEED
;IT AS A COUNTER WHEN LATER WRITE
;RANGE OF BYTES TO DISK.
STY ONEIOBUF ;PUT BYTE TO WRITE IN PARM LIST.
STA LEN2RDWR+1 ;PUT HI BYTE IN FM PARM LIST IN
;CASE THIS IS A L-PARM & WE NEED
;IT AS COUNTER WHEN LATER WRITE
;RANGE OF BYTES TO DISK.
LDA #4 ;PUT WRITE OPCODE IN FM PARM LIST
STA OPCODEFM
LDA #1 ;PUT ONE-BYTE SUBCODE IN PARM LST
STA SUBCODFM
JSR FMDRIVER ;CALL FM DRV TO WRITE 1RST BYTE.
LDA LEN2RDWR+1 ;PUT HI BYTE TO WRITE IN PARM LST
STA ONEIOBUF
JMP FMDRIVER ;GO WRITE HI BYTE TO FILE.
*=================================
* READ/WRITE A RANGE OF BYTES
*=================================
RDWRANGE STY CURIOBUF ;PUT ADR OF OUTPUT BUF IN PRM LST
STA CURIOBUF+1
LDA #2 ;SET SUBCODE FOR RANGE OF BYTES.
JMP VRFYRWNG ;GO CALL THE FILE MANAGER TO WRITE
;DATA TO THE DISK. NEXT VERIFY
;THE INFO & CLOSE THE FILE.
*=================================
* CALL FM DRIVER & THEN CLOSE FILE
*=================================
CLOSEFM JSR FMDRIVER ;CALL THE FM DRIVER 2 READ/WRITE.
JMP CMDCLOSE ;GO CLOSE THE FILE.
*========================================
* GO ISSUE A FILE-TYPE-MISMATCH ERROR MSG
*========================================
TOTYPMIS JMP TYPMISM ;GO HANDLE MISMATCH ERROR.
*=================================
* LOAD COMMAND HANDLER
*=================================
CMDLOAD JSR CLOSEALL ;CLOSE ALL FILES (EXCEPT ACTIVE
;EXEC FILE).
OPENLOAD JSR HNDLCMD ;GO OPEN THE FILE.
LDA #%00100011 ;SET BITS IN (A) TO RESTRICT LOAD
;CMD 2 APLSFT ($02), INTGR ($01)
;OR A-TYPE ($20) FILES.
AND FILTYPFM ;TYPE FOUND (VIA OPEN FUNCTION).
BEQ TOTYPMIS ;ERR -NOT ONE OF THE ABOVE TYPES.
;GO ISSUE TYPE-MISMATCH ERR MSG.
STA FILTYPFM ;SAVE TYPE WANTED IN FM PARM LIST
LDA ACTBSFLG ;CHK WHICH LANG IS ACTIVE:
; INT=$00, FP=$40, A(RAM)=$80)
BEQ LODINTGR ;BRANCH IF USING INTEGER.
LDA #2 ;CODE FOR APPLESOFT (FP).
JSR SELCTBSC ;CHK IF TYPE WANTED IS APPLESOFT.
JSR RDADRLEN ;READ LENGTH OF THE FP PRGM FROM
;THE 1RST 2 BYTES OF THE FILE.
* CHK TO SEE IF THERE IS ENOUGH ROOM
* BETWEEN PRGM START POS'N & MEMSIZ
* TO ACCOMODATE FILE.
CLC ;ADD LNGTH OF FILE 2 START OF PGM
ADC TXTTAB ;(NORMALLY, $801).
TAX ;SAVE LOW BYTE OF PRGEND IN (X).
TYA ;RETRIEVE HI BYTE OF LEN FROM (Y)
ADC TXTTAB+1
CMP MEMSIZ+1
BCS TOTOOLRG ;BRANCH IF NOT ENOUGH ROOM.
;(GO ISSUE PRGM-TOO-LARGE MSG.)
* PRGM IS SHORT ENOUGH TO BE
* ACCOMODATED IN FREE MEMORY SPACE.
*
* SET ZERO-PAGE POINTERS.
STA PRGEND+1 ;SET END OF PRGM POINTER.
STA VARTAB+1 ;SET START OF VARIABLE SPACE.
STX PRGEND ;PRGEND: VAL IN TXTTAB + LENGTH.
STX VARTAB ;VARTAB: VAL IN TXTTAB + LENGTH.
LDX TXTTAB
LDY TXTTAB+1
JSR LODINTFP ;DESIGNATE WHERE IN FREE MEMORY 2
;LOAD PRGM & THEN GO LOAD IT.
JSR INITIOHK ;POINT THE I/O HOOKS AT DOS.
JMP (RLOCNTRY) ;NORMALLY PTS TO SETLINKS ($D4F2)
;ROUTINE IN BASIC WHICH SETS
;IMPORTANT Z-PAGE POINTERS,
;CLEARS OUT VARIABLES, RESETS STK
;PTR & THEN ADJUSTS LINKS IN EACH
;PROGRAM LINE.
;EVENTUALLY, EXECUTION FLOWS INTO
;BSC'S WRMSTART (RESTART, $D43C).
;IF THE LOAD CMD WAS CALLED VIA
;THE RUN CMD, EXECUTION BRANCHES
;BACK 2 THE RUNFPINT ($A4DC) PART
;OF THE RUN CMD (AFTER ADJUSTING
;THE STACK).
;IF LOAD WAS NOT CALLED FROM RUN,
;THEN THE THE RESTART ($D43C)
;PORTION OF BASIC EVENTUALLY
;REQUESTS FURTHER PRGM OR KEYBRD
;INPUT & ANOTHER CMD IS PARSED.
*---------------------------------
* LOAD AN INTEGER PROGRAM
*---------------------------------
LODINTGR LDA #1 ;CODE 4 INTEGER BASIC FILE TYPE.
JSR SELCTBSC ;CHK IF INTEGER BASIC IS ACTIVE.
;IF NOT, SWTCH FROM FP 2 INTEGER.
JSR RDADRLEN ;READ 1RST 2 BYTES OF FILE TO GET
;LENGTH OF PRGM TO LOAD.
SEC ;CALC START OF PRGRM.
LDA HIMEM ;(HIMEM - LENADRBF.)
SBC LENADRBF
TAX
LDA HIMEM+1
SBC LENADRBF+1
BCC TOTOOLRG ;LENGTH > HIMEM SO ISSUE ERR MSG.
TAY
CPY LOMEM+1 ;CHK IF PRGM < = LOMEM.
BCC TOTOOLRG ;START OF PRGM TOO LOW, SO GO
BEQ TOTOOLRG ;ISSUE PRGM-TOO-LARGE ERROR MSG.
STY INTPGMST+1 ;SET START-OF-PRGM POINTER.
STX INTPGMST
*=================================
* GO DO THE ACTUAL LOAD.
* (COMMON LOAD ROUT'N FOR
* FP OR INTEGER LOAD CMDS.)
*=================================
LODINTFP STX CURIOBUF ;DESIGNATE LOAD ADDR AS I/O BUF
STY CURIOBUF+1 ;IN THE FM PARAMETER LIST.
JMP CLOSEFM ;USE FILE MANAGER TO LOAD PRGM.
*=================================
* COMMON CODE USED TO READ THE
* BLOAD ADDRESS, BLOAD LENGTH
* OR LOAD LENGTH FROM THE DISK.
*=================================
RDADRLEN LDA ADLENADR ;GET ADR OF TWO-BYTE INPUT BUFFER
STA CURIOBUF ;(LENADRBF, $AA60) FRM RELOCATBL
LDA ADLENADR+1 ;CONSTANTS TBL & DESIGNATE IT AS
STA CURIOBUF+1 ;THE I/O BUF IN THE FM PARM LIST.
LDA #0 ;PUT LENGTH TO READ = 2 BYTES IN
STA LEN2RDWR+1 ;THE FM PARM LIST.
LDA #2
STA LEN2RDWR
LDA #3 ;PUT READ OPCODE IN FM PARM LIST.
STA OPCODEFM
LDA #2 ;INDICATE WANT 2 READ RNG OF BYTS
STA SUBCODFM
JSR FMDRIVER ;GO READ IN THE ADDR (OR LENGTH).
LDA LENADRBF+1 ;GET HI BYTE OF ADR (OR LENGTH)
;JUST READ FROM DISK.
STA LEN2RDWR+1 ;PUT VAL JUST RD IN PARM LIST IN
;CASE JUST READ LENGTH (SO KNOW
;HOW MUCH TO READ WHEN READ MAIN
;BODY OF FILE).
TAY ;SAVE HI BYTE IN (Y).
LDA LENADRBF ;DO LIKEWISE WITH LOW BYTE.
STA LEN2RDWR
RTS
*=================================
* CLOSE FILE & ISSUE A PROGRAM-
* TOO-LARGE ERROR MESSAGE.
*=================================
TOTOOLRG JSR CMDCLOSE ;CLOSE FILE.
JMP TOOLARGE ;ISSUE ERROR MSG.
*=================================
* SELECT DESIRED BASIC
*=================================
* CHK IF DESIRED BASIC IS UP OR NOT
* (SWITCH BASIC IF NECESSARY).
SELCTBSC CMP FILTYPFM ;TYPE WANTED = TYPE FOUND?
BEQ SELBSRTN ;YES - BASIC WANTED IS ACTIVE.
LDX NDX2CMD ;SAVE INDEX 2 PRESENT CMD IN CASE
STX NEXTCMD ;WE ARE USING INTEGER & MUST LOAD
;INTEGER FILE CALLED "APPLESOFT"
;IN ORDER TO LOAD A(RAM).
LSR ;SHIFT TYPE WANTED TO SEE WHICH
;BASIC TO SWITCH INTO.
BEQ SWTCH2FP ;SWITCH FROM INTEGER 2 APPLESOFT.
JMP CMDINT ;SWITCH FROM APPLESOFT 2 INTEGER.
* SWITCHING FROM INT TO APPLESOFT
* SO COPY NAME OF FILE FROM PRIMARY
* TO SECONDARY NAME BUF IN CASE WE
* HAVE TO USE RAM-BASED APPLESOFT.
SWTCH2FP LDX #29 ;30 BYTES TO COPY (0 TO 29).
PRIM2SND LDA PRIMFNBF,X ;GET BYTE FROM PRIMARY.
STA SCNDFNBF,X ;COPY IT TO SECONDARY.
DEX
BPL PRIM2SND ;BRANCH IF MORE BYTES TO COPY.
JMP CMDFP ;EXECUTE THE FP COMMAND.
SELBSRTN RTS ;DESIRED BASIC WAS ACTIVE.
*=================================
* RUN COMMAND HANDLER
*=================================
CMDRUN LDA ACTBSFLG ;CHK WHICH BASIC IS CURRENT.
BEQ LOAD4RUN ;BRANCH IF USING INTEGER BASIC.
STA RUNTRUPT ;SET THE RUN INTERCEPT FLAG TO
;SIGNAL THAT WE ARE ABOUT TO
;INTERRUPT THE RUN COMMAND TO DO
;LOAD. ($40=A(ROM), $80=A(RAM).)
LOAD4RUN JSR CMDLOAD ;GO LOAD THE PROGRAM.
;************* NOTE *************
;* THE "JSR" IS ACTUALLY A *
;* PLACEBO BECAUSE AFTER FILE *
;* IS LOADED, EXECUTION GOES IN2*
;* BASIC & THEN RE-ENTERS DOS *
;* THRU THE DOS INTERCEPTS. ONCE*
;* DOS GETS ITS MITTS BACK INTO *
;* THINGS, THE RUNTRUPT FLAG IS *
;* TESTED & THEN EXECUTION FLOWS*
;* TO THE NEXT INSTRUCTION (AT *
;* RUNFPINT). THE MACHINE DOES *
;* NOT GET LOST BECAUSE THE STK *
;* PTR GETS RESET ACCORDINDLY. *
;********************************
RUNFPINT JSR CRVIADOS ;PRINT A <CR>.
JSR INITIOHK ;RESET THE I/O HKS TO PT TO DOS.
JMP (RUNTRY) ;GO EXECUTE THE PRGM.
;(RUNTRY PTS TO RUNFPROM IF USING
;A(ROM) OR POINTS TO FPRAMRUN
;IF USING A(RAM).)
*=======================================
* INTEGER BASIC'S RUN CMD ENTRY POINT.
* (RUNTRY PTS HERE WHEN INTEGER ACTIVE.)
*=======================================
RUNINTGR LDA LOMEM ;CLEAR OUT ALL VARIABLES.
STA INTVRLND ;ZERO OUT INTEGER BASIC'S CURRENT
LDA LOMEM+1 ;VARIABLE POINTER.
STA INTVRLND+1
JMP (CHAINTRY) ;GO INTO INTEGER BASIC 2 EXECUTE.
*=================================
* CHAIN COMMAND HANDLER
*=================================
CMDCHAIN JSR OPENLOAD ;LOAD THE INTEGER PRGM.
JSR CRVIADOS ;PRINT A <CR>.
JSR INITIOHK ;POINT I/O HOOKS AT DOS.
JMP (CHAINTRY) ;GO INTO INTEGER BASIC 2 EXECUTE.
*=================================
* A(ROM)'S RUN ENTRY POINT.
* (RUNTRY POINTS HERE IF A(ROM)
* BASIC IS ACTIVE.)
*=================================
RUNFPROM JSR SETZPTRS ;CLEAR OUT ALL VARIABLES.
STA PROMPT ;ZERO OUT PROMPT & ON-ERROR FLAG.
STA ERRFLG
JMP NEWSTT ;JUMP INTO BASIC TO EXECUTE PRGM.
*=================================
* A(RAM)'S RUN ENTRY POINT.
* (RUNTRY POINTS HERE IF A(RAM)
* VERSION OF BASIC IS UP.)
*=================================
FPRAMRUN JSR CLRFPRAM ;CLEAR ALL VARIABLES.
STA PROMPT ;ZERO OUT PROMPT & ON ERROR FLAG.
STA ERRFLG
JMP RUNFPRAM ;GO RUN THE PROGRAM.
#

View File

@@ -0,0 +1,956 @@
*=================================
* WRITE COMMAND HANDLER.
*=================================
CMDWRITE JSR COMRDWR ;CALL COMMON READ/WRITE ROUTINE.
;FIND NAMED BUF, ELSE A FREE BUF.
;OPEN FILE IF NOT ALREADY OPEN.
;POS'N FILE PTR IF R- OR B-PARMS
;WERE ISSUED.
LDA #5 ;SET CONDITION 5.
STA OPUTCOND
JMP FINSHCMD ;XIT WITH CONDITION 5 SET SO THAT
;THE NEXT TIME A PRINT STATEMENT
;IS ENCOUNTERED, EXECUTION WILL
;FLOW VIA COUT & THE DOS HKS TO
;SEND CHARS TO THE NAMED FILE.
*=================================
* READ COMMAND HANDLER.
*=================================
CMDREAD JSR COMRDWR ;CALL COMMON READ/WRITE ROUTINE.
;FIND NAMED BUF, ELSE FIND A FREE
;BUFFER. OPEN FILE IF NOT ALREADY
;OPEN. POS'N FILE PTR IF R- OR
;B-PARMS WERE ISSUED WITH CMD.
LDA #1 ;SET CONDNFLG TO SIGNAL READING.
STA CONDNFLG
JMP FINSHCMD ;XIT WITH OPUTCOND=0 & CONDNFLG=1
;EXECUTION EVENTUALLY FLOWS BACK
;INTO APPLESOFT. WHEN APPLESOFT
;PICKS UP A SUBSEQUENT "INPUT" OR
;"GET" STATEMENT, IT PRINTS A
;PROMPT. DOS INTERCEPTS OUTPUT
;VIA OPUTINCP ($9EBD). WHEN THE
;SETTING OF CONDNFLG IS DETECTED,
;THE MACHINE IS DIRECTED TO TAKE
;DATA FROM THE DISK.
*=================================
* CODE COMMON TO READ/WRITE.
*=================================
COMRDWR JSR GETBUFF ;LOCATE A DOS BUF WITH SAME NAME,
;ELSE LOCATE A FREE BUF.
BCC BUFS4RW ;BRNCH IF MATCHING BUF WAS FOUND.
JSR CMDOPEN ;FILE NOT ALREADY OPN, SO OPEN IT
JMP CKRBOPTN ;GO CHK IF R- & B-PARMS ISSUED.
BUFS4RW JSR BUFS2PRM ;COPY ADDRS OF THE VARIOUS DOS
;BUFFERS TO THE FM PARAMETER LIST
* CHK IF R- OR B-PARAMETERS
* WERE ISSUED WITH COMMAND.
CKRBOPTN LDA CUMLOPTN ;CHK IF R- OR B-PARMS ISSUED.
AND #%00000110 ;(R=$04, B=$02.)
BEQ RDWRRTN ;NO - SKIP POS'NING OF FILE PTR.
* COPY B- & R-PARMS FROM OPTION
* PARSED TABLE TO FM PARM LIST.
LDX #3
CPYBPARM LDA RECPRSD,X ;GET VALUE OF PARAMETER.
STA RECNMBFM,X ;STORE IT IN PARM LIST.
DEX ;4 BYTES TO COPY (3 TO 0).
BPL CPYBPARM
* CALL THE FILEMANAGER
* WITH THE POSITION OPCODE.
BK2APND LDA #$0A ;OPCODE FOR POSITION.
STA OPCODEFM ;PUT IT IN THE FM PARAMETER LIST.
JSR FMDRIVER ;CALL FM 2 DO THE POS'N FUNCTION.
RDWRRTN RTS
*=================================
* INIT COMMAND HANDLER.
*=================================
CMDINIT LDA #%01000000 ;CHK TO SEE IF V(OLUME) OPTION
AND CUMLOPTN ;WAS ISSUED WITH INIT COMMAND.
BEQ VOL254 ;NO V-PARM ISSUED, SO USE A DFLT
;VOLUME VALUE OF 254.
LDA VOLPRSD ;A VOL VAL WAS ISSUED, SO USE IT
BNE OTHRVOL ;(BUT ONLY IF IT IS NOT ZERO).
VOL254 LDA #254 ;USE VOL 254 AS DEFAULT VALUE.
STA VOLPRSD
OTHRVOL LDA ADOSTART+1 ;HI BYTE OF DOS LOAD ADDR FROM
;DOS'S MAIN VARIABLE TABLE.
STA SUBCODFM
LDA #11 ;OPCODE FOR INIT COMMAND.
JSR HNDLCMD1 ;CALL FM COMMAND HANDLER TO DO
;THE INIT COMMAND.
JMP CMDSAVE ;GO SAVE THE "HELLO" FILE & THEN
;EXIT TO THE CALLER OF THE INIT
;CMD. (NORMALLY RTNS TO AFTRCMD
;($A17D) LOCATED IN THE COMMAND
;PARSING & PROCESSING ROUTINES.)
*=================================
* CATALOG COMMAND HANDLER.
*=================================
CMDCATLG LDA #6 ;CATALOG OPCODE.
JSR HNDLCMD1 ;CALL CMD HANDLER TO DO CATALOG.
LDA VOLFM ;GET VOLUME # FROM FM PARM LIST
STA VOLPRSD ;& PUT IT IN THE PARSED TABLE.
RTS ;EXIT TO CALLER OF CATALOG CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;LOCATED IN THE CMD PARSING AND
;PROCESSING ROUTINES.)
*=================================
* FP COMMAND HANDLER.
*=================================
CMDFP LDA #$4C ;(A) = OPCODE FOR "JMP".
JSR SETROM ;TEST 2 SEE IF LANGUAGE WANTED IS
;ON CARD OR MOTHERBOARD.
BEQ TODOSCLD ;ROM VERSION OF FP WAS PRESENT ON
;EITHER CARD OR MOTHERBOARD SO GO
;DO A COLDSTART.
* USING MACHINE WITH INTEGER IN ROM.
*
* ASSUME USING "SYSTEM MASTER" DISK
* SO TRY TO RUN AN INTEGER PRGM
* CALLED "APPLESOFT". WHEN RUN, THE
* PRGM CALLED "APPLESOFT" LOADS A
* RAM OR DISK-BASED VERSION OF FP
* BASIC THAT IS CONTAINED IN A BINARY
* FILE CALLED "FPBASIC". THIS LATTER
* FILE IS ALSO HOUSED ON THE SYSTEM
* MASTER DISK.
LDA #0 ;SET ACTIVE BASIC FLAG TO DENOTE
STA ACTBSFLG ;USING INTEGER.
LDY #30
JSR BLNK1RST ;BLANK OUT THE PRIMARY FILE NAME
;BUFFER (30 BYTES LONG).
* COPY THE NAME OF THE INTEGER FILE
* CALLED "APPLESOFT" INTO THE PRIMARY
* FILE NAME BUFFER.
LDX #9 ;ONLY 9 CHARS IN NAME "APPLESOFT"
CPYAPPLE LDA RUNTRUPT,X ;GET CHARS OF NAME.
STA PRIMFNBF-1,X ;STORE THEM IN PRIMARY NAME BUF
DEX ;REDUCE COUNTER.
BNE CPYAPPLE ;MORE CHARS TO COPY.
LDA #$C0 ;SET CONDNFLG TO DESIGNATE USING
STA CONDNFLG ;RAM VERSION OF APPLESOFT.
JMP CMDRUN ;GO RUN FILE CALLED "APPLESOFT"
;WHICH LOADS A RAM VERSION OF
;FP BASIC CONTAINED IN A BINARY
;FILE CALLED "FPBASIC".
*=================================
* INT COMMAND HANDLER.
*=================================
CMDINT LDA #$20 ;OPCODE FOR "JSR".
JSR SETROM ;TEST TO SEE IF LANGUAGE WANTED
;IS ON CARD OR MOTHERBOARD.
BEQ INTPRSNT ;INTEGER BASIC IS PRESENT (EITHER
;ON CARD OR MOTHERBOARD).
* INTEGER BASIC NOT PRESENT
* ON CARD OR MOTHERBOARD.
NOLNGINT LDA #1 ;SET ERROR CODE FOR LANGUAGE-NOT-
JMP ERRHNDLR ;AVAILABLE MSG & GO EXIT.
* INTEGER BASIC PRESENT ON DEVICE.
INTPRSNT LDA #0 ;CAUSE DESIRED BASIC IS PRESENT,
STA RUNTRUPT ;ZERO OUT THE RUN INTERCEPT FLAG
;CAUSE WE WON'T BE LOADING A LANG
TODOSCLD JMP DOSCOLD ;GO INTO THE COLDSTART ROUTINE.
*=================================
* SELECT DESIRED BASIC
*=================================
* TEST CARD OR MOTHERBOARD TO INSURE
* THAT DEVICE CONTAINING THE ROM
* VERSION WE WANT IS SELECTED.
* BASICCLD ($E000) CONTAINS A "JMP"
* OR "JSR" INSTRUCTION IF DEALING
* WITH FP OR INTEGER ROM RESPECTIVELY.
SETROM CMP BASICCLD ;TEST CARD OR MOTHERBOARD.
;(IE.CHK WHICHEVER DEVICE IS UP.)
BEQ DVICERTN ;LANG WNTD ON PRESENT ROM DEVICE.
* LANGUAGE WAS NOT ON DEVICE SELECTED
* ABOVE, SO SPECIFICALLY TEST CARD
* IN SLOT 0. (P.S. COULD CHANGE ADDRS
* IF WANT CARD IN DIFFERENT SLOT.)
STA $C080 ;READ ENABLE SLOT0.
CMP BASICCLD ;CHECK IDENTIFYING BYTE.
BEQ DVICERTN ;BRANCH IF ROM WANTED IS ON CARD.
* ROM WANTED WAS NOT ON CARD.
* WE MAY HAVE JUST TESTED CARD TWICE
* SO NOW SPECIFICALLY TEST MOTHERBOARD.
STA $C081 ;TEST MOTHERBOARD.
CMP BASICCLD ;CHECK IDENTIFYING BYTE.
DVICERTN RTS ;EXIT WITH THE SWITCHES POINTING
;AT THE LAST DEVICE TESTED.IF THE
;DESIRED LANGUAGE IS PRESENT, THE
;SWITCHES ARE LEFT WITH THE
;APPROPRIATE DEVICE SELECTED.
*=================================
* EXEC COMMAND HANDLER.
*=================================
CMDEXEC JSR CMDOPEN ;GO OPEN THE FILE TO BE EXECED.
LDA CURFNADR ;GET ADDR OF CURRENT FILENAME BUF
STA EXECBUFF ;& DESIGNATE AS EXEC'S NAME BUF.
LDA CURFNADR+1
STA EXECBUFF+1
LDA PRIMFNBF ;SET EXEC FLAG TO A NON-ZERO VAL.
STA EXECFLAG ;(USE 1RST CHAR OF FILE NAME.)
BNE POSNCHKR ;ALWAYS - GO POS'N FILE PTR IF
;NECESSARY.
;NOTE: ACTUAL EXECING OF STATMNTS
;DOES NOT OCCUR UNTIL AFTER THE
;COMPUTER RETURNS TO BASIC'S
;RESTART ($D43C) ROUTINE. WHEN
;INPUT IS REQUESTED, EXECUTION
;FLOWS VIA DOS HKS INTO OPUTINCP
;($9EBD). HERE THE EXECFLAG IS
;TESTED & DISCOVERED TO BE SET.
;AS RESULT, THE READEXEC ($A682)
;ROUTINE IS USED 2 READ DATA FROM
;THE EXEC FILE. THE STATEMENTS
;ARE INTERPRETED AS IF THEY WERE
;ENCOUNTERED IN THE IMMED MODE.
*=================================
* POSITION COMMAND HANDLER
*=================================
CMDPOSN JSR GETBUFF ;LOCATE BUF WITH SAME NAME, ELSE
;LOCATE A FREE BUFFER.
BCC BUFS4PSN ;ALREADY OPEN -SKIP NEXT INSTRUC.
JSR CMDOPEN ;GO OPEN THE FILE.
JMP POSNCHKR ;BYPASS NEXT INSTRUC, CAUSE JUST
;OPENED FILE & PARM LIST ALREADY
;CONTAINS ADRS OF DIF DOS BUFS.
BUFS4PSN JSR BUFS2PRM ;GET ADR OF DOS BUFS FROM CHAIN
;BUF & PUT THEM IN FM PARM LIST.
POSNCHKR LDA CUMLOPTN ;CHK TO SEE IF A NON-ZERO R-PARM
AND #%00000100 ;WAS ISSUED WITH CMD.
BEQ DONEPOSN ;R-PARM WAS ZERO, SO GO EXIT
;(IE. DON'T MOVE FILE POINTER).
* A NON-ZERO R-PARM WAS ISSUED, SO GO MOVE
* THE FILE POINTER FORWARD BY READING
* ONE BYTE AT A TIME. WHEN A <CR> IS
* ENCOUNTERED, REDUCE THE COUNT OF THE
* RELATIVE FIELD POSITIONS LEFT TO MOVE.
* WHEN THE COUNT EQUALS ZERO, WE ARE
* DONE POSITIONING.
CKPSNDUN LDA RECPRSD ;CHECK COUNT.
BNE POSNMORE
LDX RECPRSD+1
BEQ DONEPOSN ;R-PRM HAS BEEN COUNTED DWN TO 0,
;SO WE ARE DONE POSITIONING.
DEC RECPRSD+1 ;REDUCE COUNT OF R-PARM (IE. # OF
POSNMORE DEC RECPRSD ;FIELDS MOVED FORWARD) FOR NEXT
;TIME AROUND.
PSNFIELD JSR RDTXTBYT ;GO READ A TEXT FILE BYTE.
BEQ ENDATERR ;IF BYTE JUST READ = $00,THEN RAN
;OUT OF DATA. A ZERO BYTE CAN BE
;OBTAINED FROM AN INCOMPLETELY
;FILLED DATA SECTOR. OR, IF THE
;FILE ENDS ON A SECTOR BOUNDARY,
;A $00 CAN ALSO BE ACQUIRED FROM
;A ZEROED-OUT T/S LINK OR A
;ZEROED-OUT DATA PAIR (TRK/SEC
;VALUES) LISTED IN A T/S LIST.
CMP #$8D ;WAS BYT A FIELD-DELIMITING <CR>?
BNE PSNFIELD ;NO -GO READ THE NEXT BYTE IN THE
;SAME FIELD.
BEQ CKPSNDUN ;YES - GOT END-OF-FIELD MARKER SO
;BRANCH BACK TO REDUCE THE FIELD
;COUNT & SEE IF WE'RE DONE
;POSITIONING YET.
DONEPOSN RTS ;EXIT - EITHER DONE POSITIONING,
;ELSE R-PARM WAS 0 TO START WITH
;& THERE4 NO POSITIONING NEEDED.
;EXIT 2 CALLER OF COMMAND. OFTEN
;RETURNS 2 AFTRCMD ($A17D) LOC'D
;IN THE CMD PARSING & PROCESSING
;ROUTINES.
*=================================
* WRITE-ONE-DATA-BYTE SUBROUTINE.
*=================================
WRITEXT JSR CKBSCRUN ;CHK IF BASIC IS RUNNING A PRGM.
BCS CLOSZERO ;NOT RUNNING, SO GO CLOSE FILE,
;RESET TO CONDITION 0 & THEN DO A
;WARMSTART. (REMEMBER, WRITE CMD
;IS RESTRICTED TO DEFERRED MODE.)
LDA ASAVED ;RETRIEVE BYTE TO WRITE.
STA ONEIOBUF ;PUT IT IN FM PARM LIST.
LDA #4 ;SET PARM LIST TO WRITE ONE BYTE.
STA OPCODEFM
LDA #1
STA SUBCODFM
JMP FMDRIVER ;GO TO FM DRV TO WRITE DATA BYTE.
*=================================
* ROUTINE TO READ A DATA BYTE.
*=================================
READTEXT JSR CKBSCRUN ;CHK IF BASIC IS RUNNING A PRGM.
BCS CLOSZERO ;BASIC NOT RUNNING SO GO CLOSE
;FILE, RESET 2 CONDITION 0 & DO A
;WARMSTART. (REMEMBER READ CMD
;IS RESTRICTED 2 DEFERRED MODE.)
LDA #6 ;SET COND'N6 -IGNORE INPUT PROMPT
SETCOND STA OPUTCOND
JSR RDTXTBYT ;GO READ TEXT FILE DATA BYTE.
BNE NOTEND ;IF BYTE READ <> 0, THEN HAVEN'T
;HIT END-OF-FILE MARKER YET.
* RAN OUT OF DATA. PICKED UP A $00 BYTE
* EITHER FROM PARTIALLY FULL DATA SECTOR,
* A ZEROED-OUT T/S LINK OR A ZEROED-OUT
* DATA PAIR (TRK/SEC VALUES LISTED IN A
* T/S LIST).
JSR CLOSEONE ;RAN OUT OF DATA SO CLOSE FILE.
LDA #3 ;USING CONDITION 3?
CMP OPUTCOND ;IE. HNDLING AN INPUT STATEMENT?
BEQ DONEPOSN ;YES - JUST GO TO AN "RTS".
ENDATERR LDA #5 ;NO - THERE4 GOT OUT-OF-DATA ERR.
JMP ERRHNDLR ;GO HANDLE ERROR.
NOTEND CMP #$E0 ;LOWERCASE?
BCC SAVIT ;BRANCH IF UPPERCASE.
AND #$7F ;CONVERT LOWER TO UPPER IN ORDER
;2 FOOL CAPTST ROUTINE ($FD7E)
;IN MONITOR ROM.
SAVIT STA ASAVED ;SAVE CHAR READ.
LDX XSAVED ;GET INDEX TO INPUT BUFFER.
BEQ TOEXIT ;BRANCH IF 1RST CHAR.
DEX ;TURN HI BIT ON IN PREVIOUS CHAR
LDA BUF200,X ;STORED IN BUF200 TO CONVERT TO
ORA #$80 ;LOWERCASE IF NECESSARY.
STA BUF200,X
TOEXIT JMP DOSEXIT ;GO TO DOS'S EXIT ROUTINE.
*==================================
* CHECK IF BASIC IS RUNNING A PRGM.
*==================================
CKBSCRUN PHA ;SAVE (A) ON STK.
LDA ACTBSFLG ;WHICH BASIC IS UP?
BEQ INTBASIC ;BRANCH IF USING INTEGER.
* USING APPLESOFT SO NOW CHECK IF
* IN IMMEDIATE OR DEFERRED MODE.
* (IF LINE NUMBER BYTES ARE
* GREATER THAN OR EQUAL TO DECIMAL
* 65280 ($FF IN HI BYTE), THEN THE
* COMPUTER ASSUMES THAT WE'RE USING
* THE IMMEDIATE MODE.)
LDX CURLIN+1 ;CHK HI BYTE OF LINE #.
INX ;IF $FF --> $00, THEN # > = 65280
BEQ IMEDMODE ;BRANCH IF USING IMMEDIATE MODE.
* FP APPEARS TO BE RUNNING A PRGM
* BUT, MAYBE CURLIN+1 WAS ZAPPED
* (POSSIBLY AS PART OF A PROTECTION
* SCHEME) SO BETTER ALSO CHECK THE
* PROMPT.
LDX PROMPT
CPX #"]" ;USING AN APPLESOFT PROMPT?
BEQ IMEDMODE ;YES - SO MUST BE IN IMMED MODE.
RUNNING PLA ;GET SAVED (A) BACK FROM STK.
CLC ;SIGNAL PRGM IS RUNNING.
RTS
INTBASIC LDA RUNMODE ;CHK INTGR BASIC'S RUN MODE FLG.
BMI RUNNING ;IF NEG, INT BASIC IN DEFERRED.
IMEDMODE PLA ;GET SAVED (A) BACK FROM STK.
SEC ;SIGNAL IN IMMEDIATE MODE.
RTS
*====================================
* CLOSE FILE, SET CONDITION0, & EXIT.
*====================================
CLOSZERO JSR CLOSEONE ;CLOSE OPEN FILE.
JSR RESTAT0 ;RESET TO CONDITION 0.
JMP DOSEXIT ;GO TO DOS'S EXIT ROUTINE.
*=================================
* EXEC'S READ DATA ROUTINE.
*=================================
READEXEC JSR PT2EXEC ;POINT THE A3L/H POINTER AT BUF
;THAT WE'RE EXECING IN.
JSR BUFS2PRM ;COPY ADDRS OF THE VARIOUS DOS
;BUFS FROM THE CHAIN BUF & PUT
;THEM IN THE FM PARAMETER LIST.
LDA #3 ;SET CONDITION 3 SO PROCESS DATA
BNE SETCOND ;INPUT FROM THE DISK.
*=================================
* READ A TEXT FILE BYTE.
*=================================
RDTXTBYT LDA #3 ;SET FM PRM LIST 2 READ ONE BYTE.
STA OPCODEFM
LDA #1
STA SUBCODFM
JSR FMDRIVER ;CALL FM DRIVER TO READ A BYTE.
LDA ONEIOBUF ;LOAD (A) WITH BYTE JUST READ.
RTS
*=================================
* POINT THE A3L/H POINTER AT
* BUFFER THAT WE'RE EXECING IN.
*=================================
PT2EXEC LDA EXECBUFF+1 ;GET ADR OF DOS BUF USING 2 EXEC.
STA A3L+1 ;PUT IT IN POINTER.
LDA EXECBUFF
STA A3L
RTS
*=================================
* THE FILE MANAGER DRIVER.
*=================================
FMDRIVER JSR FILEMGR ;CALL FM MANAGER TO DO FUNCTION.
* RETURN HERE AFTER DOING THE FUNCTION.
* (CAUSE, USE STACK TO GET BACK TO
* ORIGINAL CALLER OF FUNCTION.)
* IF WE JUST DID A READ FUNCTION &
* THE LAST BYTE READ WAS FROM A DATA
* SECTOR, THEN ENTER WITH (C)=0.
* (NOTE THAT IT MAKES NO DIFFERENCE
* IF THAT DATA BYTE WAS A $00 OR NOT.)
* HOWEVER, IF WE ARE DEALING WITH A
* ZEROED-OUT T/S LINK OR A ZEROED-OUT
* DATA-PAIR BYTE FROM A T/S LIST,
* THEN ENTER WITH CARRY SET.
AFTRFUNC BCC FMDRVRTN ;(C) = 0 = NO ERRORS.
LDA RTNCODFM ;GET RETURN CODE FRM FM PARM LIST
CMP #5 ;"END-OF-DATA" ERROR?
BEQ TOAPPTCH ;YES -NOT HANDLED LIKE OTHER ERRS
;FILE ENDS AT A FULL DATA SEC SO
;WE ENCOUNTERED A ZEROED-OUT T/S
;LINK OR A ZEROED-OUT DATA PAIR
;(TRK/SEC VALUES LISTED IN A T/S
;LIST).
JMP OTHRERR ;ONLY TAKE IF GOT AN ERROR OTHER
;THAN AN END-OF-DATA ERROR.
TOAPPTCH JMP APNDPTCH ;GO HANDLE END-OF-DATA ERROR.
NOP
BK2FMDRV JSR CKIFAPND ;<---NOTE: APNDPTCH RETURN HERE!!
;GO CHK IF THE APPEND FLAG IS ON.
LDX #0 ;ZERO-OUT THE ONE-DATA-BYTE BUF
STX ONEIOBUF ;IN THE FM PARAMETER LIST. (ALSO
;REFERRED TO AS THE LOW BYTE OF
;CURIOBUF.)
FMDRVRTN RTS ;RETURN TO CALLER OF FM DRIVER.
*=================================
* SELECTED ERROR PROCESSING.
*=================================
* NOTE: PROGRAMMERS WHO ACCESS DOS
* FROM ASSEMBLY LANGUAGE PROGRAMS
* SHOULD TAKE SPECIAL NOTE OF THE
* THE FORMATTED DISASSEMBLY TITLED
* "DISASSEMBLY OF ERRORS".
SYNTXERR LDA #11
BNE ERRHNDLR ;ALWAYS.
NOBUFERR LDA #12
BNE ERRHNDLR ;ALWAYS.
TOOLARGE LDA #14
BNE ERRHNDLR ;ALWAYS.
TYPMISM LDA #13
*=================================
* DOS'S MAIN ERROR-HANDLER ROUTINE
*=================================
ERRHNDLR STA ASAVED ;SAVE RETURN CODE FOR LATER USE.
JSR RESTATIN ;RESET THE FOLLOWING FLAGS TO 0:
; OPUTCOND, CONDNFLG & RUNTRUPT.
LDA ACTBSFLG ;CHK IF INT OR FP BASIC ACTIVE.
BEQ WASINT ;BRANCH IF USING INTEGER.
;(ONERR FLAG NOT APPLIC TO INT.)
LDA ERRFLG ;CHK IF BASIC'S ONERR FLAG IS ON.
BMI ONERRACT ;YES - SKIP PRINTING OF ERROR MSG
;CAUSE WE EVENTUALLY WANT 2 GO 2
;OUR OWN CUSTOMIZED ERROR-HNDLING
;ROUTINE.
WASINT LDX #0 ;INITIALIZE INDEX TO TABLE OF
;OFFSETS TO ERRORS.
JSR PRDOSERR ;GO PRINT <RTN>, BELL, <RTN>.
LDX ASAVED ;GET SAVED RETURN CODE.
JSR PRDOSERR ;GO PRINT THE ERROR MESSAGE.
JSR CRVIADOS ;PRINT A <CR>.
ONERRACT JSR INITIOHK ;RESET I/O HKS TO POINT TO DOS.
JSR CKBSCRUN ;CHK IF BASIC IS RUNNING A PRGM:
; (C) = 0 IF RUNNING.
; (C) = 1 IF IMMEDIATE.
LDX ASAVED ;GET SAVED RETURN CODE.
LDA #3 ;SET (A) = 3 IN CASE FALL THRU TO
;GO TO BASIC'S ERROR HANDLING
;ROUTINE. THE MAGIC # OF 3 ALLOWS
;BSCERHLR ($D865) TO CONDITION
;(C) = 0 AND (Z) = 1 IN ORDER TO
;COMPLY WITH THE BASIC ROUTINE
;THAT IS RESPONSIBLE FOR PRINTING
;BASIC'S ERROR MESSAGES.
BCS DOWRM ;BASIC IS NOT RUNNING.
TOBSCERR JMP (ADBSCERR) ;2 BASIC'S ERROR HANDLING ROUTINE
;(BSCERHLR, $D865).
DOWRM JMP (TOWRMVEC) ;TO BASIC'S WARMSTART ROUTINE
;(RESTART, $D43C).
*=================================
* PRINT THE DOS ERROR MESSAGE.
*=================================
PRDOSERR LDA OFF2ERR,X ;USE ERROR CODE TO GET OFFSET TO
;ERROR MESSAGE.
TAX ;(X) = OFFSET INTO THE TABLE
;CONTAINING THE TEXT OF THE DOS
;ERROR MESSAGES.
MORERMSG STX TEMPBYT ;SAVE OFFSET INTO TXT TABLE.
LDA ERRTXTBL,X ;GET CHAR OF ERROR MESSAGE.
PHA ;SAVE IT ON STACK.
ORA #$80 ;TURN HI BIT ON 2 SATISFY MONITOR
JSR GODSPLY ;GO PRINT VIA TRUE OUTPUT HANDLER
LDX TEMPBYT ;RESET OFFSET TO TABLE OF TEXT.
INX ;KICK INDEX UP FOR NXT CHR OF MSG
PLA ;GET ORIG CHAR BACK IN (A).
BPL MORERMSG ;BRANCH IF MORE CHRS IN MSG 2 PRT
RTS ;ALL BUT LAST CHR IN MSG ARE POS.
*=================================
* PUT VOL, DRV, AND SLOT VALUES
* PLUS THE ADR OF THE PRIMARY FILE
* NAME BUFFER IN FM PARAMETER LIST
*=================================
CPY2PARM LDA VOLPRSD ;FROM PARSED TABLE.
STA VOLFM
LDA DRVPRSD ;FROM PARSED TABLE.
STA DRVFM
LDA SLOTPRSD ;FROM PARSED TABLE.
STA SLOTFM
LDA ADRPFNBF ;GET THE ADR OF THE PRIMARY FILE
STA FNAMBUFM ;NAME BUF FROM THE CONSTANTS TBL
LDA ADRPFNBF+1 ;AND PUT IT IN THE FM PARM LIST.
STA FNAMBUFM+1
LDA A3L ;SAVE ADR OF CURRENT DOS FILENAME
STA CURFNADR ;BUF IN TABLE OF DOS VARIABLES.
LDA A3L+1
STA CURFNADR+1
RTS
*===================================
* COPY NAME OF FILE FROM THE PRIMARY
* FILENAME BUFFER TO THE APPROPRIATE
* DOS NAME BUFFER LOCATED IN THE
* CHAIN OF DOS BUFFERS.
* THIS ASSIGNS (OR RE-ASSIGNS) A DOS
* BUFFER TO THE FILE WE WANT TO OPEN.
* THE HIGHEST NUMBERED (LOWEST IN
* MEMORY) FREE DOS BUFFER IS USED.
*===================================
CPYPFN LDY #29 ;30 BYTES TO COPY (0 TO 29).
CPYPRIM LDA PRIMFNBF,Y ;GET CHAR FROM PRIMARY.
STA (A3L),Y ;STORE IT IN DOS NAME BUF.
DEY ;REDUCE COUNTER.
BPL CPYPRIM ;MORE CHARS TO COPY.
RTS
*====================================
* GET THE ADDRS OF THE VARIOUS DOS
* BUFS FROM THE CURRENT DOS CHAIN
* BUF & PUT THEM IN THE FM PARM LIST.
*====================================
BUFS2PRM LDY #30 ;GET ADR OF FM WORK BUF, T/S LIST
ADRINPRM LDA (A3L),Y ;BUF, DATA SECTOR BUF & NEXT
STA WRKBUFFM-30,Y ;DOS FILE NAME BUF FROM CHAIN
INY ;PTRS BUF & PUT IN FM PARM LIST.
CPY #38 ;(PS. ADDR OF NEXT DOS FILE NAME
BNE ADRINPRM ;BUF IS NOT USED BY DOS.)
RTS
*=================================
* RESET CONDNFLG & OPUTCOND TO 0.
*=================================
RESTAT0 LDY #0
STY CONDNFLG
STY OPUTCOND
RTS
*==================================
* LOCATE BUFFER WITH SAME NAME.
* IF THAT FAILS, LOCATE A FREE BUF.
*==================================
GETBUFF LDA #0 ;DEFAULT HI BYTE OF PTR TO 0.
STA A5L+1 ;(IE. ASSUME NO FREE BUFS AVAIL.)
JSR GETFNBF1 ;PT A3L/H AT 1RST DOS FILE NAME
;BUFFER IN THE DOS BUFFER CHAIN.
JMP FNCHAR1 ;GO GET 1RST CHR OF NAME FRM BUF.
GETFNLNK JSR GETNXBUF ;GET ADR OF NXT NAME BUF IN CHAIN
;FROM CHAIN POINTERS BUF(WHICH IS
;OFFSET 37 & 36 BYTES FROM 1RST
;CHAR OF PRESENT FILE NAME BUF).
BEQ NOFNMTCH ;LINK ZEROED OUT=END OF BUF CHAIN
FNCHAR1 JSR GETFNBY1 ;GET 1RST CHR OF NAME FRM NAM BUF
BNE NXFNBUF ;TAKE BRANCH IF BUF NOT FREE.
LDA A3L ;BUF WAS FREE, THERE4 POINT THE
STA A5L ;A5L/H POINTERS AT THE FREE BUF.
LDA A3L+1
STA A5L+1
BNE GETFNLNK ;ALWAYS.
NXFNBUF LDY #29 ;BUF WASN'T FREE SO CMP NAME OF
CMPFNCHR LDA (A3L),Y ;OWNER WITH NAME OF FILE IN
CMP PRIMFNBF,Y ;PRIMARY FILE NAME BUF. (START
;WITH LAST CHAR FIRST.)
BNE GETFNLNK ;CHAR DIDN'T MATCH, SO LOOK FOR
;ANOTHER BUF THAT MIGHT HAS SAME
;FILE NAME.
DEY ;THAT CHAR MATCHED. HOW ABOUT
;REST OF CHARS IN NAME?
BPL CMPFNCHR ;30 CHARS IN NAME (IE. 0 TO 29).
CLC ;(C)=0 TO SIGNAL NAMES MATCHED.
RTS
NOFNMTCH SEC ;LINK ZEROED OUT.
RTS
*===================================
* POINT THE A3L/H POINTER AT THE
* FIRST DOS FILE NAME BUFFER IN
* THE DOS BUFFER CHAIN. (IE. LOWEST
* NUMBERED BUFFER, BUT HIGHEST IN
* MEMORY.)
*===================================
GETFNBF1 LDA ADOSFNB1 ;GET 1RST LINK TO CHAIN OF BUFS.
LDX ADOSFNB1+1
BNE SETNXPTR ;ALWAYS.
*=================================
* GET ADR OF NXT FILENAME BUF IN
* CHAIN FROM THE CURRENT CHAIN
* POINTERS BUF (WHICH IS OFFSET
* 37 & 36 BYTES FROM 1RST CHAR
* IN PRESENT DOS FILE NAME BUF).
*---------------------------------
GETNXBUF LDY #37 ;OFFSET TO CHAIN BUF.
LDA (A3L),Y ;PICK UP ADR OF NEXT NAME BUF.
BEQ GETNXRTN ;IF HI BYTE=$00, LINK ZEROED OUT.
TAX ;SAVE HI BYTE IN (X).
DEY ;OFFSET FOR LOW BYTE.
LDA (A3L),Y ;PUT ADR OF FILE NAME BUF IN PTR.
SETNXPTR STX A3L+1 ;PUT HI BYTE IN POINTER.
STA A3L ;PUT LOW BYTE IN POINTER.
TXA ;GET HI BYTE BACK IN (A).
GETNXRTN RTS
*=================================
* GET 1RST CHAR OF FILE NAME
* FROM DOS FILE NAME BUFFER.
*=================================
GETFNBY1 LDY #0 ;BUF IS FREE IF 1RST BYTE = $00.
LDA (A3L),Y ;ELSE 1RST BYTE = 1RST CHAR OF
RTS ;NAME OF FILE WHICH OWNS BUF.
*=================================
* CHECK IF THE CURRENT FILE NAME
* BUFFER BELONGS TO AN EXEC FILE.
* (AFTER ALL, WE DON'T WANT TO
* PREMATURELY CLOSE A FILE IF WE
* ARE USING IT TO EXEC - WOULD BE
* LIKE BURYING OURSELVES ALIVE).
*=================================
CKEXCBUF LDA EXECFLAG ;CHK TO SEE IF EXECING.
BEQ NOTEXCBF ;BRANCH IF NOT EXECING.
LDA EXECBUFF ;WE ARE EXECING, THERE4 CHK IF BUF
CMP A3L ;BELONGS TO THE EXEC FILE.
BNE CKEXCRTN ;NO.
LDA EXECBUFF+1 ;MAYBE - LOW BYTES MATCHED SO
CMP A3L+1 ;CHK HI BYTES OF ADR.
BEQ CKEXCRTN ;YES, EXEC BUF = CURRENT BUF.
NOTEXCBF DEX ;NOT EXECING, SO REDUCE (X) TO
;MAKE SURE THAT Z-FLAG IS OFF.
;(PS. (X) WAS ORIG CONDITIONED TO
;A LARGE NON-ZERO VAL ON ENTRY
;TO GETFNBF1, THERE4, IF NOW DEX,
;THEN INSURE Z-FLAG OFF.)
CKEXCRTN RTS ;EXIT WITH:
; Z-FLAG = 1 IF EXECING.
; = 0 IF NOT EXECING.
*======================================
* CHK IF FILE TYPE WANTED = TYPE FOUND.
*======================================
CHKFTYPE EOR FILTYPFM ;TYPE FOUND (VIA OPEN FUNCTION).
BEQ CKTYPRTN ;BRNCH IF TYPE WANTED=TYPE FOUND.
AND #%01111111 ;MAYBE MATCHED-DISREGARD LOCK BIT
BEQ CKTYPRTN ;BRANCH IF MATCHED.
JSR CMDCLOSE ;NAMED FILE IS WRONG TYPE, SO GO
JMP TYPMISM ;CLOSE FILE & EXIT WITH A TYPE-
;MISMATCH ERROR MESSAGE.
CKTYPRTN RTS ;TYPE WANTED = TYPE FOUND.
*=================================
* BUILD THE DOS BUFFERS.
*=================================
* POINT A3L/H AT FILENAME FIELD
* IN THE LOWEST NUMBERD (HIGHEST
* IN MEMORY) DOS BUFFER.
BILDBUFS SEC ;IRREL, MIGHT AS WELL BE A "NOP".
LDA ADOSFNB1 ;GET ADDR OF 1RST FILE NAME FIELD
STA A3L ;& PUT IT IN A3L/H POINTER.
LDA ADOSFNB1+1
STA A3L+1
* GET # OF MAXFILES WANTED & STORE
* IT IN THE COUNTER (TEMPBYT).
LDA MXFILVAL
STA TEMPBYT
* FREE BUFFER BY ZEROING OUT THE
* FIRST BYTE OF THE DOS BUFFER'S
* FILE NAME FIELD.
ZDOSBUFN LDY #0
TYA
STA (A3L),Y
* POINT LINK IN CHAIN POINTERS BUF
* AT FM WORK AREA BUFFER.
LDY #30 ;SET (Y) TO INDEX 1RST LINK IN
;CHAIN POINTERS BUFFER.
SEC
LDA A3L ;SUBT 45 FROM LOW BYTE OF ADDR
SBC #45 ;OF NAME BUF TO CALC LOW BYTE OF
STA (A3L),Y ;ADDR OF FM WORK BUF & PUT IT IN
PHA ;THE CHAIN PTR BUF & ON THE STK.
LDA A3L+1 ;SUBT (C) FROM HIGH BYTE OF ADR
SBC #0 ;OF NAME BUF TO GET HI BYTE OF
;FM WRK BUF ADR.
INY ;KICK UP (Y) TO INDEX ADDR OF HI
;BYTE OF LINK IN CHAIN POINTERS.
STA (A3L),Y ;STORE HI BYTE OF ADR OF FM WRK
;BUF IN THE LINK.
;(NOTE: ABOVE CALCS EFFECT (A)
;BUT NOT A3L/H.)
* POINT LINK IN CHAIN POINTERS BUFFER
* AT T/S LIST SECTOR BUFFER.
TAX ;PUT HI BYTE OF ADDR OF FM WRK BUF
DEX ;IN (X) & KICK IT DOWN SO IT
;INDEXES HI BYTE OF T/S LIST BUF.
;(T/S LST BUF = $100 BYTES LONG.)
PLA ;GET LOW BYTE OF ADDR OF FM WRK
PHA ;BACK FROM STK.
INY ;KICK UP INDEX TO LINK IN CHAIN
;POINTERS BUFFER.
STA (A3L),Y ;PUT LOW BYTE OF FM WRK BUF ADR
;IN LINK BUFFER'S POINTERS.
TXA ;GET HI BYTE T/S LIST BUF IN (A).
INY ;KICK UP INDEX IN CHAIN BUF.
STA (A3L),Y ;PUT HI BYTE OF LINK IN PTRS BUF.
* POINT LINK IN CHAIN POINTERS BUF
* AT DATA SECTOR BUFFER.
TAX ;PUT HI BYTE OF ADDR OF T/S LIST
DEX ;BUF IN (X) & KICK IT DOWN TO
;CORRESPOND TO HI BYTE OF ADDR
;OF DATA SEC BUF.
PLA ;GET LOW BYTE OF T/S LIST SEC BUF
PHA ;FROM STACK & USE IT FOR LOW BYTE
;OF DATA SEC BUF (CAUSE THEY ARE
;EXACTLY 1 PAGE APART).
INY ;KICK UP INDEX TO CHAIN BUF.
STA (A3L),Y ;PUT LOW BYTE OF DATA SEC BUF
;IN LINK.
INY ;KICK UP INDEX TO CHAIN BUF.
TXA ;GET HI BYTE OF ADR OF T/S LIST
STA (A3L),Y ;BUF & DESIGN8 AS HI BYT OF LINK.
* REDUCE COUNTER FOR # OF BUFS TO BUILD.
DEC TEMPBYT ;IF COUNTER GOES TO 0, THEN JUST
BEQ ZLNK2NXT ;DID LAST BUF & SHOULD 0 OUT LNK.
* NOT DONE ALL BUFS YET SO POINT
* LINK IN CHAIN POINTERS BUFFER
* AT NEXT FILE NAME FIELD.
TAX ;SET (X) = LOW BYTE OF ADR OF DATA
;SECTOR BUFFER.
PLA ;GET LOW BYTE OF ADDR OF DATA
;SECTOR BUF BACK OFF STK.
SEC ;SUBT 38 FROM LOW BYTE OF DATA SEC
SBC #38 ;ADR TO INDEX NEXT NAME BUF.
INY ;KICK UP INDEX TO CHAIN BUF.
STA (A3L),Y ;STORE LOW BYTE OF ADR OF NEXT
PHA ;NAME BUF IN LINK & THEN SAVE
;IT ON STK.
TXA ;GET HI BYTE OF ADR OF DATA SEC
SBC #0 ;BUF FROM (X) & SUBT (C) (IN CASE
;CROSS PAGE BOUNDARY) TO GET
;(A) = HI BYTE OF NEXT NAME BUF.
INY ;KICK INDEX UP TO CHAIN PTRS BUF
STA (A3L),Y ;& STORE HI BYTE OF NEXT NAME BUF
;IN LINK.
* POINT A3L/H AT NEXT NAME BUF.
STA A3L+1
PLA
STA A3L
JMP ZDOSBUFN ;GO BACK TO FREE NEXT NAME BUF
;& BUILD MORE DOS BUFFERS.
* NO MORE BUFS TO BUILD SO ZERO OUT
* THE LINK THAT WOULD NORMALLY POINT
* TO THE NEXT NAME BUFFER.
ZLNK2NXT PHA ;SAVE LOW BYTE OF ADR OF DATA BUF
;ON STK.
LDA #0 ;ZERO OUT LINK TO NEXT NAME BUF.
INY
STA (A3L),Y
INY
STA (A3L),Y
* CHK WHICH BASIC IS ACTIVE.
LDA ACTBSFLG ;CHK IF ACTV BASIC IS FP OR INT.
BEQ SETINTPT ;BRANCH IF INTEGER.
* USING APPLESOFT, SO INITIALIZE
* MEMSIZ & FRETOP (STRING STORAGE)
* TO A VALUE 1 BYTE GREATER THAN
* HIGHEST MEMORY LOCATION AVAILABLE
* TO BASIC PROGRAM.
PLA
STA MEMSIZ+1
STA FRETOP+1
PLA
STA MEMSIZ
STA FRETOP
RTS ;EXIT TO CALLER OF MAXFILES CMD.
;(USUALLY EXITS 2 AFTRCMD ($A17D)
;LOCATED IN THE DOS CMD PARSING
;AND PROCESSING ROUTINES.)
* USING INTEGER, SO SET HIMEM AND
* PROGRAM POINTER (INTPGMST).
SETINTPT PLA
STA HIMEM+1
STA INTPGMST+1
PLA
STA HIMEM
STA INTPGMST
RTS ;EXIT TO CALLER OF MAXFILES CMD.
;(USUALLY EXITS 2 AFTRCMD ($A17D)
;LOCATED IN THE DOS CMD PARSING
;AND PROCESSING ROUTINES.)
O

View File

@@ -0,0 +1,842 @@
*===================================
* INITIALIZE THE I/O HOOKS SO THAT
* DOS INTERCEPTS ALL INPUT & OUTPUT.
*===================================
* FOR INSTANCE, IF A ROUTINE ACCESSES
* "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.
* THEN THE INTERCEPTS ARE SET AS FOLLOWS:
* ADINPTCP: INPTINCP --> KSW: INPTINCP.
* ADOPUTCP: OPUTINCP --> CSW: OPUTINCP.
* CHECK IF INPUT HOOK NEEDS TO BE RESET.
INITIOHK LDA KSW+1
CMP ADINPTCP+1
BEQ CKOUTHK ;INPUT HK ALREADY POINTS 2 DOS'S
;INPUT HNDLER SO GO CHK OUTPUT HK
* RESET INPUT HOOK TO POINT TO DOS.
STA KSWTRUE+1 ;KSW: KEYIN --> KSWTRUE: KEYIN.
LDA KSW
STA KSWTRUE
LDA ADINPTCP ;ADINPTCP:INPTINCP-->KSW:INPTINCP
STA KSW
LDA ADINPTCP+1
STA KSW+1
* CHECK IF OUTPUT HOOK NEEDS TO BE RESET.
CKOUTHK LDA CSW+1
CMP ADOPUTCP+1
BEQ SETHKRTN ;OUTPUT HK ALREADY PTS TO DOS'S
;OUTPUT HANDLER, SO EXIT.
* RESET OUTPUT HOOK TO POINT TO DOS.
STA CSWTRUE+1 ;CSW: COUT1 --> CSWTRUE: COUT1.
LDA CSW
STA CSWTRUE
LDA ADOPUTCP ;ADOPUTCP:OPUTINCP-->CSW:OPUTINCP
STA CSW
LDA ADOPUTCP+1
STA CSW+1
SETHKRTN RTS
*========================================
* DOS COMMAND TEXT TABLE ($A884 - $A908).
*========================================
* THE NAMES OF THE DIFFERENT DOS COMMANDS
* CAN READILY BE CHANGED BY ALTERING THE
* INFORMATION IN THIS TABLE. IF YOU
* DECIDE TO MESS AROUND WITH THIS TABLE,
* BE SURE TO:
* - LET THE 1RST CMD CREATE A NEW FILE.
* (FOR EXPLANATION, SEE FMXTNTRY
* ROUTINE ($AAFD) IN LINEAR DIS'MBLY.)
* - AVOID CREATING NEW DOS CMD NAMES
* THAT DUPLICATE BASIC CMD NAMES.
* - USE POSITIVE ASCII CHARS FOR ALL BUT
* THE LAST CHAR OF EACH NAME.
* - ENTER THE LAST CHAR IN EACH NAME IN
* NEGATIVE ASCII FORM.
* - SHIFT SUBSEQUENT NAMES TO KEEP ALL
* CHARS CONTIGUOUS IF YOU CREATE
* SHORTER NAMES.
* - DON'T EXPAND THE TABLE BEYOND $A908.
* - END THE TABLE WITH A $00 BYTE.
*========================================
CMDTXTBL DCI 'INIT' ; ($A884 - $A887)
DCI 'LOAD' ; ($A888 - $A88B)
DCI 'SAVE' ; ($A88C - $A88F)
DCI 'RUN' ; ($A890 - $A892)
DCI 'CHAIN' ; ($A893 - $A897)
DCI 'DELETE' ; ($A898 - $A89D)
DCI 'LOCK' ; ($A89E - $A8A1)
DCI 'UNLOCK' ; ($A8A2 - $A8A7)
DCI 'CLOSE' ; ($A8A8 - $A8AC)
DCI 'READ' ; ($A8AD - $A8B0)
DCI 'EXEC' ; ($A8B1 - $A8B4)
DCI 'WRITE' ; ($A8B5 - $A8B9)
DCI 'POSITION' ; ($A8BA - $A8C1)
DCI 'OPEN' ; ($A8C2 - $A8C5)
DCI 'APPEND' ; ($A8C6 - $A8CB)
DCI 'RENAME' ; ($A8CC - $A8D1)
DCI 'CATALOG' ; ($A8D2 - $A8D8)
DCI 'MON' ; ($A8D9 - $A8DB)
DCI 'NOMON' ; ($A8DC - $A8E0)
DCI 'PR#' ; ($A8E1 - $A8E3)
DCI 'IN#' ; ($A8E4 - $A8E6)
DCI 'MAXFILES' ; ($A8E7 - $A8EE)
DCI 'FP' ; ($A8EF - $A8F0)
DCI 'INT' ; ($A8F1 - $A8F3)
DCI 'BSAVE' ; ($A8F4 - $A8F8)
DCI 'BLOAD' ; ($A8F9 - $A8FD)
DCI 'BRUN' ; ($A8FE - $A901)
DCI 'VERIFY' ; ($A902 - $A907)
HEX 00 ; ($A908)
;$00 BYTE DENOTES END OF TABLE.
*========================================
* TABLE OF ATTRIBUTES & VALID OPTIONS
* THAT ARE ASSOCIATED WITH EACH COMMAND.
* ($A909 - $A940)
*========================================
* NOTE: ANY ALTERATIONS TO THIS TABLE
* SHOULD BE DONE WITH A DEGREE OF CAUTION
* BECAUSE SEVERAL PARAMETERS ACQUIRE
* CERTAIN DEFAULT VALUES IN THE ACTUAL
* COMMAND-HANDLING ROUTINES. WITH JUST
* A BIT OF INSPECTION OF THE HANDLING
* ROUTINES HOWEVER, YOU SHOULD BE ABLE TO
* SAFELY MAKE EXTENSIVE CHANGES IF YOU SO
* DESIRE.
*
* THIS TABLE IS INDEXED BY A VALUE
* CORRESPONDING TO THE PARSED DOS
* COMMAND. TWO BYTES OF INFORMATION
* ARE ASSOC WITH @ CMD. A SET BIT
* DENOTES THE FOLLOWING:
*
* FIRST BYTE
* 7 6 5 4 3 2 1 0
* . . . . . . . .
* . . . . . . . ...CMD CAN CREATE NEW FILE IF FILE
* . . . . . . . NOT FOUND.
* . . . . . . ......CMD RESTRICTED TO DEFERRED MODE.
* . . . . . .........VALUE FOR MAXFILES REQUIRED.
* . . . . ............VALUE FOR PR# OR IN# REQUIRED.
* . . . ...............2ND FILENAME NEEDED (RENAME CMD)
* . . ..................FILE NAME APPLICABLE TO CMD
* . . (EXPECTED BUT NOT NECESSARILY
* . . REQUIRED.)
* . .................... DO DOS CMD EVEN IF NO NAME GIVEN
* ....................... INTERPRET AS BASIC CMD IF NO NAM
* SECOND BYTE
* 7 6 5 4 3 2 1 0
* . . . . . . . .
* . . . . . . . ...A(DDRESS) PARAMETER ALLOWED.
* . . . . . . ......B(YTE) PARAMETER ALLOWED.
* . . . . . .........R(ECORD) # OR R(EL FIELD POS'N)
* . . . . . PARAMETER ALLOWED.
* . . . . ............L(ENGTH) PARAMETER ALLOWED.
* . . . ...............S(LOT) PARAMETER ALLOWED.
* . . ..................D(RIVE) PARAMETER ALLOWED.
* . .....................V(OLUME) PARAMETER ALLOWED.
* ........................C, I, OR O PARAMETER ALLOWED.
CMDATTRB HEX 2170 ;INIT 00100001 01110000
HEX A070 ;LOAD 10100000 01110000
HEX A170 ;SAVE 10100001 01110000
HEX A070 ;RUN 10100000 01110000
HEX 2070 ;CHAIN 00100000 01110000
HEX 2070 ;DELETE 00100000 01110000
HEX 2070 ;LOCK 00100000 01110000
HEX 2070 ;UNLOCK 00100000 01110000
HEX 6000 ;CLOSE 01100000 00000000
HEX 2206 ;READ 00100010 00000110
HEX 2074 ;EXEC 00100000 01110100
HEX 2206 ;WRITE 00100010 00000110
HEX 2204 ;POSITION 00100010 00000100
HEX 2378 ;OPEN 00100011 01111000
HEX 2270 ;APPEND 00100010 01110000
HEX 3070 ;RENAME 00110000 01110000
HEX 4070 ;CATALOG 01000000 01110000
HEX 4080 ;MON 01000000 10000000
HEX 4080 ;NOMON 01000000 10000000
HEX 0800 ;PR# 00001000 00000000
HEX 0800 ;IN# 00001000 00000000
HEX 0400 ;MAXFILES 00000100 00000000
HEX 4070 ;FP 01000000 01110000
HEX 4000 ;INT 01000000 00000000
HEX 2179 ;BSAVE 01000001 01111001
HEX 2071 ;BLOAD 01000000 01110001
HEX 2071 ;BRUN 01000000 01110001
HEX 2070 ;VERIFY 00100000 01110000
*=================================
* OPTION CHARACTER SYMBOL TABLE.
* ($A941 - $A94A)
* THESE CHARACTERS ARE FREQUENTLY
* CHANGED AS PART OF A PROTECTION
* SCHEME.
*=================================
OPTNTXT ASC "VDSLRBACIO"
*=================================
* OPTIONS ISSUED TABLE
* ($A94B - $A954)
* A SET BIT IN THE FOLLOWING BIT
* POSITIONS (OF CUMLOPTN) DENOTE
* THE OPTIONS THAT WERE ISSUED
* WITH THE COMMAND.
*=================================
OPTNISSD HEX 40 ;V(OLUME) PARAMETER.
HEX 20 ;D(RIVE) PARAMETER.
HEX 10 ;S(LOT) PARAMETER.
HEX 08 ;L(ENGTH) PARAMETER.
HEX 04 ;R(ECORD # OR R(EL FIELD POS'N).
HEX 02 ;B(YTE) PARAMETER.
HEX 01 ;A(DDRESS) PARAMETER.
HEX C0 ;C(OMMAND).
HEX A0 ;I(NPUT).
HEX 90 ;O(UTPUT).
*=================================
* TABLE OF VALID RANGES ASSOC
* WITH EACH OPTION CHARACTER.
* ($A955 - $A970)
* (THESE VALUES ARE FREQUENTLY
* CHANGED IN AN EFFORT TO
* "ENCHANCE" DOS OR IMPLEMENT
* A PROTECTION SCHEME. FOR
* EXAMPLE, THE UPPER RANGE ASSOC
* WITH THE L-PARAMETER IS OFTEN
* CHANGED TO ALLOW DOS TO HANDLE
* LARGER FILES.
*=================================
OPTNRNG HEX 0000FE00 ;($A955 - $A958) V: (0 - 254).
HEX 01000200 ;($A959 - $A95C) D: (1 - 2).
HEX 01000700 ;($A95D - $A960) S: (1 - 7).
HEX 0100FF7F ;($A961 - $A964) L: (1 - 32767).
HEX 0000FF7F ;($A965 - $A968) R: (0 - 32767).
HEX 0000FF7F ;($A969 - $A96C) B: (0 - 32767).
HEX 0000FFFF ;($A96D - $A970) A: (0 - 65535).
*==================================
* TEXT TABLE OF DOS ERROR MESSAGES.
* ($A971 - $AA3E)
* NOTE THAT ONLY THE LAST CHARACTER
* OF EACH TEXT MESSAGE IS WRITTEN
* IN NEGATIVE ASCII FORM. (THESE
* MESSAGES ARE FREQUENTLY ALTERED
* IN COMMERCIAL PROGRAMS.)
*==================================
;CORRESPONDING ERROR CODE & ADDRS
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 ELSE,
;ILLEGAL ARGUMENTS ISSUED 4 IN#,
;PR#, MAXFILES CMDS OR FOR A, B,
;R, L, S, D, V, C, I, OR O OPT'NS
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)
HEX 8D ;<CR> NO CODE ($AA3E)
*=================================
* TABLE OF OFFSETS TO THE ERROR
* MSG TEXT TABLE ($AA3F - $AA4E).
* (HACKERS OFTEN SWAP THESE BYTES
* AROUND SO ERRONEOUS ERROR MSGS
* WILL BE USED.)
*=================================
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
HEX BB ; - 15
*=================================
* DOS MAIN ROUTINE VARIABLES.
* ($AA4F - $AA65)
*=================================
CURFNADR DS 2 ;PTS TO CURRENT FILENAME BUF
;(USUALLY PRIMFNBF, $AA75).
;(NORMALLY LOADED FROM FNAMBUFM
;$B5C3, IN FM PARM LIST).
CONDNFLG DS 1 ;STATUS FLAG:
;$00 = WARMSTART, $01 = READ
;$80 = COLDSTART, $C0 = A(RAM).
OPUTCOND DS 1 ;CHAR SWITCH OUTPUT CONDITION FLG
; $00 = EVALUATE START OF INPUT
; LINE.
; $01 = GOT A DOS CTRL CHAR SO
; COLLECT DOS COMMAND.
; $02 = NOT A DOS CMD, SO JUST
; PRT CHAR & RTN TO CALLER.
; $03 = HANDLING INPUT OR GET
; STATMENTS WHILE READING.
; $04 = WRITING DATA TO DISK.
; $05 = EVALUATE 1RST CHAR OF
; DATA LINE READ FROM DSK.
; $06 = IGNORE "?" PRMPT & RESET
; TO CONDITION 0.
CSWTRUE DA COUT1 ;ADR OF TRUE OUTPUT HANDLER.
KSWTRUE DA KEYIN ;ADR OF TRUE INPUT HANDLER.
MXFILVAL HEX 0303 ;CURRENT # OF DOS BUFS IN CHAIN
;(SECOND BYTE IS IRRELEVANT).
STKSAVED DS 1 ;($AA59) 1RST STACK PTR SAV AREA.
;(P.S. DON'T CONFUSE WITH THE
;2ND STK POINTER SAVE AREA KNOWN
;AS "STKSAV" ($B39B).
XSAVED DS 1 ;(X) SAVE AREA.
YSAVED DS 1 ;(Y) SAVE ARE.
ASAVED DS 1 ;(A) SAVE AREA.
NDX2INBF DS 1 ;INDEX TO CMD LINE IN INPUT BUF.
CIOCUMUL DS 1 ;MON/NOMON FLAG.
;CUMMULATIVE UPDATED RECORD OF
;C/I/O ARGUMENTS:
; C=$40, I=$20, O=$10, IO=$30,
; CO=$50, CI=$60, CIO=$70.
NDX2CMD DS 1 ;INDEX TO COMMAND.
LENADRBF DS 2 ;2-BYTE BUF USED 2 HOLD BLOAD ADR
;& LENGTH READ FROM DISK.
;(LEFT WITH LNGTH OF LAST BLOAD.)
NEXTCMD DS 1 ;CODE FOR PENDING COMMAND.
TEMPBYT DS 1 ;TEMPORARY STORAGE AREA.
NDX2OPTN DS 1 ;INDEX TO OPTION (USED TO INDEX
;OPTNTXT, OPTNISSD & OPTNRNG).
CUMLOPTN DS 1 ;HOLDS CUMMULTIVE RECORD OF
;OPTIONS PARSED ON CMD LINE.
*=================================
* OPTION PARSED VALUES TABLE.
* ($AA66 - $AA74)
* (CONTAINS A RECORD OF THE OPTION
* VALUES THAT WERE ISSUED WITH THE
* COMMAND. SOME OF THESE BYTES
* ARE DEFAULTED TO NON-ZERO VALS.)
*=================================
VOLPRSD DS 2 ;PARSED VOLUME NUMBER.
DRVPRSD DS 2 ;PARSED DRIVE NUMBER.
SLOTPRSD DS 2 ;PARSED SLOT NUMBER.
LENPRSD DS 2 ;PARSED LENGTH VALUE.
RECPRSD DS 2 ;PARSED RECORD OR RELATIVE FIELD
;POSITION NUMBER.
BYTPRSD DS 2 ;PARSED BYTE VALUE.
ADRPRSD DS 2 ;PARSED ADDRESS PARAMETER.
MONPRSD DS 1 ;PARSED MON/NOMON CHR CODE VALS.
*==================================
* NON-CHAIN FILE NAME BUFFERS.
* (PS. DON'T CONFUSE WITH THE
* VARIOUS FILENAME BUFS ASSOC
* WITH THE CHAIN OF DOS BUFFERS.)
*==================================
* PRIMARY FILE NAME BUFFER.
PRIMFNBF DS 30 ;($AA75 - $AA92)
* SECONDARY FILE NAME BUFFER.
SCNDFNBF DS 30 ;($AA93 - $AAB0)
*====================================
* MAIN ROUTINE CONSTANTS & VARIABLES.
* ($AAB1 - $AAB7)
*====================================
MAXDFLT DS 1 ;DEFAULT VALUE FOR # OF DOS BUFS.
;(OFTEN ALTERED N COM'CIAL PRGMS)
DCTRLCHR HEX 84 ;DOS'S CTRL CHAR:
; NORMALLY = CTRL-D, $84.
;(OFTEN CHNGD IN COM'CIAL PRGMS)
EXECFLAG DS 1 ;EXEC FLAG: $00 = NOT EXECING,
;(ELSE CONTAINS 1RST CHAR OF NAME
;OF EXEC FILE).
EXECBUFF DS 2 ;PTS TO EXEC FILE'S BUFFER.
ACTBSFLG DS 1 ;ACTIVE BASIC FLAG (INT=$00,
;A(ROM)=$40, A(RAM)=$80).
RUNTRUPT DS 1 ;RUN INTERCEPTED FLAG:
;$00 = RUN NOT INTECEPTED.
;NON-ZERO = RUN INTERCEPTED TO DO
; A LOAD.
*=================================
* TEXT OF THE WORD "APPLESOFT".
* ($AAB8 - $AAC0)
*=================================
APLSFTXT ASC "APPLESOFT"
*=================================
* FILE MANAGER'S CONSTANTS TABLE.
* ($AAC1 - $AAC8)
*=================================
ADRIOB DA IBTYPE ;PTS TO RWTS'S IOB. NOTE:THE $3E3
;VECTOR LOADS FROM ADRIOB.
ADRVTOC DA VTOCBUFF ;PTS TO VTOC SECTOR BUFFER.
ADRDIRBF DA DIRECBUF ;PTS TO DIRECTORY SECTOR BUFFER.
DOSNDPL1 DA $C000 ;PTS TO LAST BYTE OF DOS PLUS 1.
*======================================
* FILE MANAGER'S FUNCTION HNDLR ENTRY
* POINT TABLE ($AAC9 - $AAE4).
* (ALL ADDRS ARE 1 LESS THAN THE ACTUAL
* ENTRY POINT BECAUSE THE THE FUNCTIONS
* ARE ENTERED VIA A "STACK JUMP".)
*======================================
FMFUNCTB DA $B37F-1 ;NULL - EXIT WITH NO ERRORS.
DA $AB22-1 ;FNOPEN-1
DA $AC06-1 ;FNCLOSE-1
DA $AC58-1 ;FNREAD-1
DA $AC70-1 ;FNWRITE-1
DA $AD2B-1 ;FNDELETE-1
DA $AD98-1 ;FNCATLOG-1
DA $ACEF-1 ;FNLOCK-1
DA $ACF6-1 ;FNUNLOCK-1
DA $AC3A-1 ;FNRENAME-1
DA $AD12-1 ;FNPOSN-1
DA $AE8E-1 ;FNINIT-1
DA $AD18-1 ;FNERIFY-1
DA $B37F-1 ;NULL - EXIT WITH NO ERRORS.
*====================================
* FILE MANAGER READ-SUBFUNCTION ENTRY
* POINT TABLE ($AAE5 - $AAF0).
* (P.S. SUBFUNCTIONS EMPLOYING THE
* POSITION OPTION ARE AVAILABLE TO
* THE USER BUT NEVER CALLED BY DOS.)
*====================================
;SUBFUNCTION INDEX.
RDSUBTBL DA GOODFMXT-1 ;(0), EXIT.
DA READONE-1 ;(1), READ ONE BYTE.
DA READRNG-1 ;(2), READ A RANGE OF BYTES.
DA PSNRDONE-1 ;(3), POSITION & READ ONE BYTE.
DA PSNRDRNG-1 ;(4), POS'N & READ RNGE OF BYTES.
DA GOODFMXT-1 ;(5), EXIT.
*=====================================
* FILE MANAGER WRITE SUBFUNCTION ENTRY
* POINT TABLE ($AAF1 - $AAFC).
* (P.S. SUBFUNCTIONS EMPLOYING THE
* POSITION OPTION ARE AVAILABLE TO
* THE USER BUT NEVER CALLED BY DOS.)
*=====================================
;SUBFUNCTION INDEX.
WRSUBTBL DA GOODFMXT-1 ;(0), EXIT.
DA WRITEONE-1 ;(1), WRITE ONE BYTE.
DA WRITERNG-1 ;(2), WRITE A RANGE OF BYTES.
DA PSNWRONE-1 ;(3), POSITION & WRITE ONE BYTE.
DA PSNWRRNG-1 ;(4), POS'N & WRITE RNG OF BYTES.
DA GOODFMXT-1 ;(5), EXIT.
*=========================================
* FILE MANAGER EXTERNAL ENTRY POINT.
* -NOTE: THE $3D6 VECTOR LOADS FROM HERE!!
* -ENABLES USER TO ACCESS FILE MANAGER
* FROM CUSTOM ASSEMBLY LANGUAGE ROUTINES.
*=========================================
FMXTNTRY CPX #0
BEQ FMXTCMD ;ALLOW NEW FILE-SIMUL8 AN "INIT".
LDX #02 ;REQUIRES OLD FILE (SIMUL8 LOAD).
FMXTCMD STX NDX2CMD ;SET INDEX TO COMMAND.
*=================================
* FILE MANAGER PROPER.
*---------------------------------
FILEMGR TSX ;SAVE STK PTR SO WE CAN LATER RTN
STX STKSAV ;TO AFTRFUNC ($A6AB) LOCATED IN
;THE FMDRIVER ROUTINE ($A6A8).
;(NOTE THAT APPEND CMD EMPLOYS
;THE RSETPTRS ROUTINE ($B6B3) TO
;RE-ADJUST STKSAV ($B39B) SO THAT
;EXECUTION ACTUALLY RETURNS TO
;AFTRCMD ($A6AB) LOCATED IN THE
;DOS CMD PARSING AND PROCESSING
;ROUTINES.)
JSR RSTRFMWA ;COPY FM WRK BUF (IN DOS CHAIN) 2
;FM WRK AREA (NOT IN DOS CHAIN).
LDA OPCODEFM ;CHK IF OPCODE IS LEGAL.
CMP #13 ;(MUST BE LESS THAN 13.)
BCS TOERROP ;OPCODE TOO LARGE - RANGE ERROR.
ASL ;DOUBLE VAL OF OPCODE & PUT IT IN
TAX ;(X) SO IT INDEXES TABLE OF ADRS.
LDA FMFUNCTB+1,X ;STICK ADDRESS (MINUS 1) OF THE
PHA ;FUNCTION HANDLER ON THE STACK
LDA FMFUNCTB,X ;(HI BYTE FIRST).
PHA
RTS ;DO A STACK JMP TO THE FUNCTION'S
;ENTRY POINT.
TOERROP JMP RNGERROP ;GO HANDLE RANGE ERROR.
*=================================
* OPEN FUNCTION HANDLER.
*=================================
FNOPEN JSR COMNOPEN ;OPEN PREEXISTING FILE OR CREATE
;NEW FILE IF CMD ALLOWS NEW FILES
JMP GOODFMXT ;EXIT CLEANLY. EVENTUALLY RTNS TO
;AFTRFUNC ($A6AB) LOCATED IN THE
;FM DRIVER ROUTINE ($A6A8).
*=================================
* COMMON OPEN ROUTINE.
*=================================
COMNOPEN JSR ZWRKAREA ;INITIALIZE THE FM WORK AREA WITH
;DEFAULT VALUES.
;(DON'T CONFUSE WITH FM WRK BUF
;WHICH IS IN DOS BUF CHAIN.)
LDA #1 ;DESCRIBE SECTOR LENGTH AS 256
STA SECSIZWA+1 ;BYTES (IN FM WORK AREA).
* GET RECORD LENGTH FROM FM PARM
* LIST & PUT IT IN FM WORK AREA.
* (DON'T ALLOW A 0 LENGTH. IF
* ZERO, CHANGE IT TO ONE.)
LDX RECLENFM+1
LDA RECLENFM
BNE STRECLEN ;NON-ZERO REC 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
JSR GETFNTRY ;TRY 2 FIND DIRECTORY SEC 4 FILE.
BCC FILLINWA ;BRNCH IF FOUND DIR SEC WITH SAME
;NAME IN FILE DESCRIPTION ENTRY.
* THE NAMED FILE WAS NOT FOUND IN
* THE DIRECTORY, SO PREPARE A NEW
* FILE ENTRY IN CASE THE CMD CAN
* LEGALLY CREATE A NEW FILE.
STX CURDIRNX ;OFFSET TO NEW DESCRIP ENTRY IN
;CASE WANT TO CREATE A NEW FILE.
* CHECK TO SEE IF CMD CAN
* LEGALLY CREATE A NEW FILE.
LDX NDX2CMD ;(X) = INDEX REPRESENTING CMD.
LDA CMDATTRB,X ;GET 1RST BYTE CONTAINING DESCRIP
;OF THE COMMAND'S ATTRIBUTES.
LDX CURDIRNX ;(X)=INDEX FOR A NEW FILE DESCRIP
;ENTRY INTO DIRECTORY SEC.
LSR ;(C)=BIT0 OF 1RST ATTRIBUTE BYTE.
BCS CREATNEW ;IF (C)=1 CMD CAN MAKE NEW FILE.
* COMMAND CAN'T CREATE NEW FILE.
* SEE WHICH LANGUAGE WE'RE USING
* & EXIT WITH APPROPRIATE ERROR.
NEWILLGL LDA CONDNFLG ;$00=WARMSTART, $01=READING,
;$40=A(RAM), $80=COLDSTART,
;$C0=INTEGER.
CMP #$C0 ;IS INTEGER IN ROM?
BNE TOFILNOT ;NO.
JMP LNGNOTAV ;HANDLE LANGUAGE-NOT-AVAIL ERROR.
TOFILNOT JMP FILENOT ;HANDLE FILE-NOT-FOUND ERROR.
*---------------------------------
* CREATE A NEW FILE:
* - INIT FILE SIZE = 1 SEC LONG.
* - ALLOCATE SECS FOR DATA SECS
* & UPDATE FILE SIZE.
* - WRITE UPDATED VTOC TO DISK.
* - PUT LINK IN FILE DESCRIPTION
* ENTRY & UPDATE FILE SIZE.
* - WRITE UPDATED VTOC TO DISK.
* - WRITE NEW T/S LIST TO DISK.
*--------------------------------
CREATNEW LDA #0 ;INITIALIZE FILE SIZE = 1 SECTOR.
STA FIL1SIZE+1,X ;(CAUSE AT 1RST, ONLY STARTING
LDA #1 ;OUT WITH A T/S LIST SECTOR.)
STA FIL1SIZE,X
STX CURDIRNX ;SAVE BYTE OFFSET INTO DIR SEC
;FOR FILE DESCRIPTION.
JSR ASGNTKSC ;FIND TRK/SEC VALS FOR NEW FILE.
* FINISH SETTING UP PARAMETERS
* IN THE FILE MANAGER'S WORK AREA.
* (P.S. DON'T CONFUSE FM WORK AREA
* WITH THE VARIOUS WORK BUFFERS
* LOCATED IN THE DOS BUFFER CHAIN.)
LDX CURDIRNX ;OFFSET IN DIR SEC 4 NEW DESCRIP
STA FIL1TSSC,X ;PUT SEC VAL IN DIRECTORY SECTOR.
STA FIRTSSEC ;PUT SEC VALUE OF 1RST T/S LIST
;SECTOR IN THE FM WORK AREA.
STA CURTSSEC ;PUT CUR SEC VAL IN FM WRK AREA.
LDA ASIGNTRK ;DO THE SAME FOR TRACK VALUE.
STA FIL1TSTK,X
STA FIRSTSTK
STA CURTSTRK
LDA FILTYPFM ;(FROM FM PARM LIST.)
STA FIL1TYPE,X ;PUT FILE TYPE IN DIREC SEC BUF.
* WRITE DIRECTORY SECTOR BUFFER.
JSR WRDIRECT ;WRITE DIRECTORY SEC BUF IN CAT.
* WRITE T/S LIST SECTOR BUFFER.
JSR SELTSBUF ;GET ADR OF T/S LIST SEC BUF FROM
;THE FM PARM LIST.
JSR ZCURBUF ;ZERO OUT T/S LIST SECTOR BUF.
JSR WRITETS ;WRITE ZEROED OUT T/S LIST SEC.
;(IF THE WRITE SUBFUNCTION IS
;LATER ENTERED TO WRITE NEW DATA
;TO THE DISK, THE ZERO BYTES ARE
;DETECTED & USED AS SIGNALS THAT
;NEW DATA PAIR SHOULD BE WRITTEN
;INTO THE T/S LIST SECTOR.)
LDX CURDIRNX ;OFFSET IN DIREC SEC 4 NEW FILE.
LDA #6 ;DEFAULT RETURN CODE VALUE 2 THAT
STA RTNCODFM ;FOR A FILE-NOT-FOUND ERROR.
* FILL IN THE FM WORK AREA BUFFER.
* (ROUTINE COMMON TO OPENING A
* NEW OR PRE-EXISTING FILE.)
FILLINWA LDA FIL1TSTK,X ;T/S LIST TRK (FRM DIRECTORY SEC)
STA FIRSTSTK
LDA FIL1TSSC,X ;T/S LIST SEC (FRM 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 BYTNXD1R ;INDEX IN2 DIREC SEC FOR DESCRIP.
LDA #$FF ;PRETEND THAT THE LAST DATA SEC
STA RELPREV ;USED HAD A RELATIVE SECTOR #
STA RELPREV+1 ;(IN RELATION TO 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.
LDA MXIN1TSL ;DICTATE THAT A T/S LIST CAN ONLY
STA MXSCURTS ;DESCRIBE $7A (#122) DATA SECS.
;NOTE: THIS VAL 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 SEC BUFFER.
* (EVENTHOUGH IT IS NOT NEEDED BY
* THE RENAME, LOCK OR UNLOCK
* FUNCTIONS, THE FIRST T/S LIST IS
* AUTOMATICALLY READ INTO THE T/S
* LIST BUFFER IF THE FILE WAS
* FOUND.)
CLC ;(C)=0 =SIGNAL 1RST T/S LIST SEC.
JMP READTS ;GO READ IN THE T/S LIST SEC.
*==================================
* INITIALIZE (IE. 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.
* ALSO BE CAUTIONED NOT TO CONFUSE
* THE FM WORK AREA WITH ITS IMAGE
* (DOS WORK BUFFER) THAT IS HOUSED
* IN THE CHAIN OF DOS BUFFERS.)
*==================================
* ZERO OUT THE FM WORK AREA.
ZWRKAREA LDA #0
TAX ;INITIALIZE X-INDEX.
ZEROWRKA STA FMWKAREA,X ;PUT $00 BYTE IN WORK AREA.
INX
CPX #45 ;WORK AREA IS 45 BYTES LONG.
BNE ZEROWRKA
* BEGIN CUSTOMIZING THE WORK AREA.
* GET VOL, DRV, SLOT & CATALOG TRK
* VALUES FROM THE FM PARM LIST.
* PUT DRV, SLOT*16, CAT TRK AND
* COMPLEMENTED VOL # IN THE WORK
* AREA.
LDA VOLFM ;VOLUME #.
EOR #$FF ;CALC 1'S COMPLEMENT OF VOL #.
STA VOLWA
LDA DRVFM ;DRIVE #.
STA DRVWA
LDA SLOTFM ;GET SLOT #.
ASL ;CALC SLOT * 16.
ASL
ASL
ASL
TAX ;SET (X) = SLOT*16.
STX SLOT16WA
LDA #$11 ;NORMAL CAT TRK = #17.
STA TRKWA
RTS
*=================================
* CLOSE FUNCTION HANDLER.
*=================================
FNCLOSE JSR CKDATUP ;WRITE DATA SEC BUF IF NECESSARY.
JSR CKTSUPDT ;WRITE T/S LIST SEC BUF IF NEC.
JSR FIXMAP ;FREE UP SECS THAT WERE ALLOCATED
;BUT NOT USED. WHENEVER SOMETHING
;IS WRITTEN 2 THE DISK, THE WHOLE
;TRK IS ALLOCATED IN THE VTOC
;WHETHER IT IS NEEDED OR NOT.
;THERE4, ONCE DONE WRITING, GO
;BACK & FREE UP UNNEEDED SECS.
* WAS LAST OPERATION A WRITE?
LDA #%00000010 ;IF BIT 1 SET, THEN WAS WRITE.
AND UPDATFLG
BEQ TOGDFMXT ;WASN'T A WRITE SO CAN JUST EXIT
;CAUSE NO NEED TO UPDATE DIR SEC.
* LAST OPERATION WAS A WRITE, SO
* BETTER PREPARE TO FIX UP THE
* FILE-SIZE BYTES AND T/S LINKS
* IN DIRECTORY SECTORS, ETC.
JSR READVTOC ;READ VOLUME TABLE OF CONTENTS.
* READ IN ALL DIR SECS UP TO THE
* ONE CONTAINING THE FILE DESCRIP
* ENTRY FOR THE FILE WE ARE CLOSING.
LDA #0
CLC ;(C)=0=SIGNAL 2 READ 1RST DIR SEC
PURGEDIR JSR RDDIRECT ;GO READ A DIRECTORY SEC.
SEC ;(C)=1, 1RST DIR SEC ALREADY READ
DEC SECNXD1R ;INDEX FOR # OF DIRECTORY SECS.
BNE PURGEDIR ;IF 0, THEN JUST READ DIREC SEC
;PERTAINING TO THE FILE WANTED.
* UPDATE THE FILE SIZE & WRITE THE
* DIRECTORY SECTOR TO THE DISK.
LDX BYTNXD1R ;(X) = OFFSET OF FILE DESCRIPTION
;IN THE DIRECTORY SECTOR.
LDA FILENSEC ;# SECS IN FILE (FRM FM WRK AREA)
STA FIL1SIZE,X
LDA FILENSEC+1
STA FIL1SIZE+1,X
JSR WRDIRECT ;WRITE UPDATED DIRECTORY SECTOR.
TOGDFMXT JMP GOODFMXT ;CLEAN EXIT. EVENTUALLY RTNS TO
;AFTRFUNC ($A6AB) LOCATED IN THE
;FMDRIVER ROUTINE ($A6A8).
*=================================
* RENAME FUNCTION HANDLER.
*=================================
FNRENAME JSR COMNOPEN ;LOCATE FILE WITH SAME NAME & OPN
;IT IF ITS NOT ALREADY OPEN.
LDA FILTYPWA ;GET FILE TYPE (FROM WORK AREA).
BMI TOFILOCK ;ERROR-CAN'T RENAME A LOCKED FILE
LDA RENAMBUF ;GET ADR OF SECONDARY NAME BUFFER
STA A4L ;FROM FM PARM LIST & PUT IN A4L/H
LDA RENAMBUF+1
STA A4L+1
LDX CURDIRNX (X) = INDEX INTO CURRENT DIR SEC.
JSR NWDESCRP ;COPY NEW NAME TO DIREC SEC BUF.
JSR WRDIRECT ;WRIT MODIFIED DIR SEC BUF 2 DSK.
JMP GOODFMXT ;TAKE THE GOOD ROUTE HOME.
;EVENTUALLY RETURNS TO AFTRFUNC
;LOCATED IN FMDRIVER RTN ($A6A8).
F

View File

@@ -0,0 +1,957 @@
*=================================
* READ FUNCTION HANDLER.
*=================================
FNREAD LDA SUBCODFM ;CHK IF SUBCODE IS LEGAL.
CMP #5 ;(MUST BE < = 5.)
BCS TOERRSUB ;RANGE ERROR - ILLEGAL SUBCODE.
ASL ;SUBCODE*2, CAUSE 2 BYTES/ADR.
TAX ;INDEX TABLE OF SUBFUNCTION ADRS.
LDA RDSUBTBL+1,X;GET ADDR (MINUS 1) OF SUBFUNCT
PHA ;ENTRY POINT & PUT IT ON THE STK
LDA RDSUBTBL,X ;(HI BYTE FIRST). THEN DO A STACK
PHA ;JUMP TO EXECUTE THE GIVEN READ
RTS ;SUBFUNCTION.
TOERRSUB JMP RNGERRSB ;GO HANDLE RANGE ERROR.
TOFILOCK JMP FILELOKD ;GO HANDLE LOCKED FILE ERROR.
*=================================
* WRITE FUNCTION HANDLER.
*=================================
FNWRITE LDA FILTYPWA ;CHK IF FILE IS LOCKED.
BMI TOFILOCK ;ERROR - CAN'T WRITE 2 LCKD FILE.
LDA SUBCODFM ;CHK IF SUBCODE IS LEGAL.
CMP #5 ;(MUST BE < = 5.)
BCS TOERRSUB ;ERROR - ILLEGAL SUBCODE.
ASL ;SUBCODE*2, CAUSE 2 BYTES/ADR.
TAX ;INDEX TABLE OF SUBFUNCTION ADRS.
LDA WRSUBTBL+1,X;GET ADR (MINUS 1) OF SUBFUNCT
PHA ;ENTRY POINT & STICK ON THE STACK
LDA WRSUBTBL,X ;(HI BYTE FIRST). THEN DO A STACK
PHA ;JUMP TO EXECUTE THE GIVEN WRITE
RTS ;SUBFUNCTION.
*=================================
* POSITION AND READ-ONE-BYTE
* SUBFUNCTION HANDLER.
*=================================
PSNRDONE JSR CALCFPTR ;USING R-, L- & B-PARAMETERS,CALC
;THE POS'N OF FILE PTR WANTED.
*==================================
* READ-ONE-BYTE SUBFUNCTION HANDLER
*==================================
READONE JSR RDDATA ;GET DATA BYTE FROM DATA SEC BUF.
;(IF DESIRED DATA SECTOR IS NOT
;ALREADY IN MEMORY, THEN READ IT
;IN. HOWEVER, 1RST CHK IF PRESENT
;INFO IN DATA SEC NEEDS TO BE
;UPDATED SO DON'T OVERWRITE DATA
;IN BUF & LOOSE INFO.)
STA ONEIOBUF ;PUT BYTE READ IN THE 1-BYTE BUF
;CONTAINED IN THE FM PARM LIST.
JMP GOODFMXT ;EXIT THE FILE MGR. EVENTUALLY
;RTNS TO AFTRFUNC ($A6AB) LOCATED
;IN THE FMDRIVER ROUTINE ($A6A8).
*=================================
* POSITION & READ-A-RANGE-OF-BYTES
* SUBFUNCTION HANDLER.
*=================================
PSNRDRNG JSR CALCFPTR ;USING R-, L- & B-PARMS, CALC THE
;POS'N OF FILE POINTER WANTED.
*=================================
* READ-RANGE-OF-BYTES
* SUBFUNCTION HANDLER.
*=================================
READRNG JSR DECRWLEN ;DECREMENT THE # OF BYTES 2 READ.
;(DONE READING WHEN LEN2RDWR=0.)
JSR RDDATA ;GET DATA BYTE FROM DATA SEC BUF.
;(IF DESIRED DATA SECTOR IS NOT
;ALREADY IN MEMORY, THEN READ IT
;IN. HOWEVER, 1RST CHK IF PRESENT
;INFO IN DATA SEC NEEDS TO BE
;UPDATED SO DON'T OVERWRITE DATA
;IN BUF & LOOSE INFO.)
PHA ;SAVE SINGLE BYTE READ ON STK.
JSR INCIOBUF ;INC THE CUR'NT TARGET RAM MEMORY
;LOCATION (BYTRNG) & POINT A4L/H
;AT TARGET LOCATION IN I/O BUF.
LDY #0 ;INITIALIZE (Y) INDEX.
PLA ;RETRIEVE BYTE READ.
STA (A4L),Y ;PUT SINGLE BYTE READ INTO THE
;TARGET MEMORY LOCATION.
JMP READRNG ;GO BK TO READ NEXT BYTE OF DATA.
*=================================
* SUBROUTINE TO READ A DATA BYTE.
*=================================
RDDATA JSR NXTDATRD ;CHK IF DATA SEC WE WANT TO READ
;IS ALREADY IN MEMORY. IF NOT,
;READ DATA SEC INTO DATA SEC BUF.
;HOWEVER, 1RST CHK IF DAT SEC BUF
;NEEDS UPDATING SO DON'T OVRWRITE
;DATA SEC BUF & LOSE INFO.
BCS NDATERR ;BRANCH IF RAN OUT OF DATA SECS
;WHILE READING.
LDA (A4L),Y ;GET SINGLE BYTE FRM DATA SEC BUF
PHA ;SAVE IT ON STK.
JSR INCREC ;EITHER INC REC # OR BYTE OFFSET
;INTO RECORD.
JSR INCFILPT ;INC BYTE OFFSET INTO CURRENT
;DATA SEC OR, IF AT END OF SEC,
;INC THE SECTOR OFFSET INTO THE
;ENTIRE FILE.
PLA ;GET DATA BYTE RD (BACK OFF STK).
RTS
NDATERR JMP ENDOFDAT ;RAN OUT OF DATA WHILE READING.
*=================================
* POSITION & WRITE-ONE-BYTE
* SUBFUNCTION HANDLER.
*=================================
PSNWRONE JSR CALCFPTR ;USING R-, L- & B-PARMS, CALC
;POS'N OF FILE POINTER WANTED.
*=================================
* WRITE-ONE-BYTE SUBFUNCTION HNDLR
*=================================
WRITEONE LDA ONEIOBUF ;GET BYTE TO WRITE FROM ONE-BYTE
;BUFFER IN FM PARAMETER LIST.
JSR WRTDATA ;STORE DATA TO WRITE IN THE DATA
;SECTOR BUFFER. IF DATA SEC BUF
;IS FULL, THEN WRITE IT TO DISK
;AND UPDATE T/S LIST BUF.
JMP GOODFMXT ;EXIT FILE MANAGER. EVENTUALLY
;RTNS TO AFTRFUNC ($A6AB) LOCATED
;IN THE FMDRIVER ROUTINE ($A6A8).
*=================================
* POSITION & WRITE-RANGE-OF-BYTES
* SUBFUNCTION HANDLER.
*=================================
PSNWRRNG JSR CALCFPTR ;USING R-, L- & B-PARMS, CALC
;POS'N OF FILE POINTER WANTED.
*=================================
* WRITE RANGE-OF-DATA-BYTES
* SUBFUNCTION HANDLER.
*=================================
WRITERNG JSR INCIOBUF ;POINT A4L/H AT SOURCE BYTE.
LDY #0 ;SET (Y) TO INDEX SOURCE BUF.
LDA (A4L),Y ;GET BYTE TO WRITE.
JSR WRTDATA ;PUT DATA BYTE IN DATA SEC BUF.
;(WRITE DATA SEC BUF TO DISK IF
;NECESSARY. )
JSR DECRWLEN ;CHECK IF DONE WRITING. IF NOT,
;REDUCE COUNTER FOR # OF BYTES
;LEFT TO WRITE.
JMP WRITERNG ;GO BACK TO WRITE NEXT DATA BYTE.
*=================================
* SUBROUTINE WHICH WRITES BYTE.
*=================================
WRTDATA PHA ;SAVE BYTE TO WRITE ON STK.
JSR NXTDATRD ;READ NXT DATA SEC BUF IF NEEDED.
PLA ;GET DATA BYTE TO WRITE OFF STK.
STA (A4L),Y ;PUT DATA BYTE IN DATA SEC BUF.
LDA #%01000000 ;SET BIT6 TO SIGNAL DATA SEC BUF
ORA UPDATFLG ;HAS CHANGED & THEREFOR, THE DISK
STA UPDATFLG ;REQUIRES UPDATING.
JSR INCREC ;EITHER INC THE RECORD NUMBER OR
;INC THE BYTE OFFSET INTO RECORD.
JMP INCFILPT ;INC THE BYTE OFFSET INTO THE
;CURRENT DATA SECTOR. IF AT THE
;END OF SECTOR, INC THE OFFSET
;INTO THE ENTIRE FILE INSTEAD.
*=================================
* LOCK & UNLOCK FUNCTION HANDLERS.
*=================================
FNLOCK LDA #$80 ;SET HI BIT IN LOCK/UNLOCK MASK.
STA LOKUNMSK
BNE COMNLOCK ;ALWAYS.
FNUNLOCK LDA #0 ;MAKE SURE HI BIT CLR IN LOKUNMSK
STA LOKUNMSK
COMNLOCK JSR COMNOPEN ;LOCATE THE FILE WITH THE SAME
;NAME & OPEN IT.
LDX CURDIRNX ;(X) = INDEX TO FILE DESCRIPTION
;ENTRY IN THE DIRECTORY SEC BUF.
LDA FIL1TYPE,X ;GET OLD FILE TYPE.
AND #$7F ;SHUT HI BIT OFF.
ORA LOKUNMSK ;MERGE WITH LOKUNMSK 2 SET OR CLR
;(LOCK OR UNLOCK) HI BIT.
STA FIL1TYPE,X ;STICK MODIFIED FILE TYPE BACK IN
;FILE DESCRIP PART OF DIR SEC BUF
JSR WRDIRECT ;WRITE UPDATED DIREC SEC TO DISK.
TOOKFMXT JMP GOODFMXT ;EXIT FM CLEANLY. EVENTUALLY RTNS
;TO AFTRFUNC ($A6AB) LOCATED IN
;THE FMDRIVER ROUTINE ($A6A8).
*=================================
* POSITION FUNCTION HANDLER.
*=================================
FNPOSN JSR CALCFPTR ;USE R-, B- & L-PARAMETERS 2 CALC
;POSITION OF FILE POINTER WANTED.
JMP GOODFMXT ;EXIT FILE MANAGER CLEANLY.
;EVENTUALLY RETURNS TO AFTRFUNC
;($A6AB) LOCATED IN THE FMDRIVER
;ROUTINE ($A6A8).
*=================================
* VERIFY FUNCTION HANDLER.
*=================================
FNVERIFY JSR COMNOPEN ;LOCATE FILE WITH SAME NAME
;& OPEN IT.
VRFYREAD JSR NXTDATRD ;READ NEXT DATA SEC IN. (ASSUME
;DATA SEC WE WANT NOT PRESENTLY
;IN MEMORY.)
BCS TOOKFMXT ;END OF FILE DETECTED - EXIT FM.
;EVENTUALLT RETURNS TO AFTRFUNC
;($A6AB) LOCATED IN THE FMDRIVER
;ROUTINE ($A6A8).
INC FILPTSEC ;KICK UP FILE POINTER POS'N
BNE VRFYREAD ;AND THEN GO BACK TO READ NEXT
INC FILPTSEC+1 ;DATA SECTOR UNTIL ENCOUNTER END
JMP VRFYREAD ;OF FILE MARKER.
*=================================
* DELETE FUNCTION HANDLER.
*=================================
FNDELETE JSR COMNOPEN ;LOCATE FILE WITH SAME NAME AND
;THEN OPEN IT.
LDX CURDIRNX ;(X) = INDEX TO FILE DESCRIPTION
;IN DIRECTORY SECTOR BUFFER.
LDA FIL1TYPE,X ;GET FILE TYPE FROM DIR SEC BUF.
BPL ALTRNTRY ;BRANCH IF FILE NOT LOCKED.
JMP FILELOKD ;ERR - CAN'T DELETE A LOCKED FILE
;SO GO HANDLE ERR & EXIT.
* GET TRK # OF FILES 1RST T/S LIST
* FROM FILE DESCRIP ENTRY IN DIR
* SEC BUF. PUT IT IN THE WRK AREA
* & WRITE IT OVER THE LAST CHAR
* POS'N IN THE APPROPRIATE FILE
* NAME FIELD IN DIRECTORY SECTOR.
ALTRNTRY LDX CURDIRNX ;(X) = INDEX TO FILE DESCRIPTION
;ENTRY IN DIRECTORY SEC BUFFER.
LDA FIL1TSTK,X ;GET TRK # OF 1RST T/S LIST SEC.
STA FIRSTSTK ;COPY IT IN2 WORK AREA & LAST CHR
STA FIL1NAME+29,X ;POS'N OF FILE NAME FLD DSCRP
LDA #$FF ;REPLACE ORIG TRK # OF T/S LIST
STA FIL1TSTK,X ;WITH $FF TO SIGNAL FILE DELETED.
LDY FIL1TSSC,X ;PUT SEC # OF FILE'S 1RST T/S LST
STY FIRTSSEC ;IN THE WORK AREA.
JSR WRDIRECT ;WRITE MODIFIED DIREC SEC 2 DISK.
* READ T/S LIST SEC INTO T/S LIST BUF.
* (NEED THIS INFO SO KNOW WHAT SECS
* TO RELEASE.)
CLC ;(C)=0, SIGNAL 1RST T/S LIST SEC.
RDTS4DEL JSR READTS ;GO READ IN T/S LIST.
BCS DONEDEL ;BRNCH IF JUST READ LAST T/S LIST
;SEC ASSOCIATED WITH THIS FILE.
JSR SELTSBUF ;POINT A4L/H AT T/S LIST SECTOR
;BUFFER.(GET ADR FRM FM PRM LST.)
* FREE ALL SECS LISTED IN THE T/S
* LIST THAT CURRENTLY OCCUPIES THE
* T/S LIST BUFFER.
LDY #12 ;1RST DATA SEC PAIR LISTED IS
;OFFSET 12 BYTES FROM START OF
;T/S LIST BUFFER.
DELFREE STY CURDIRNX ;SET (Y) = INDEX TO THE DATA PAIR
;LISTED IN THE T/S LIST BUFFER.
LDA (A4L),Y ;GET TRK # OF DATA SEC.
BMI BYPASDEL ;NEG TRK # ILLEGAL. (CAN USE AS
;A PROTECTION SCHEME.)
BEQ BYPASDEL ;TRK # OF 0 = NO MORE DATA SECS
;LISTED IN CURRENT T/S LIST.
PHA ;SAVE TRK # OF DATA SEC ON STK.
INY ;GET SEC # OF DATA SEC.
LDA (A4L),Y
TAY ;CONDITION (Y)=SEC & (A)=TRK FOR
PLA ;ENTRY IN2 ROUT'N 2 FREE UP SECS.
JSR FREESEC ;FREE UP SECTOR FROM DELETED FILE
BYPASDEL LDY CURDIRNX ;SET (Y) 2 INDEX START DATA PAIR.
INY ;KICK UP (Y) 2 PT AT NXT DATA PR.
INY
BNE DELFREE ;IF (Y) < > 0, THEN NEVER RAN OFF
;END OF T/S LIST SEC BUF YET, SO
;GO CHK IF MORE DATA PRS TO DO.
* FREE UP SECTOR CONTAINING THE
* T/S LIST.
LDA CURTSTRK ;TRK # OF CURRENT T/S LIST SEC.
LDY CURTSSEC ;SEC # OF CURRENT T/S LIST SEC.
JSR FREESEC ;GO FREE UP THE T/S LIST SEC.
SEC
BCS RDTS4DEL ;ALWAYS.
* DONE FREEING UP ALL SECTORS
* ASSOCIATED WITH THIS FILE, SO
* NOW WRITE MODIFIED VTOC BACK
* TO THE DISK.
DONEDEL JSR WRITVTOC ;WRITE UPDATED VTOC TO DISK.
JMP GOODFMXT ;GO EXIT FM CLEANLY. EVENTUALLY
;RTNS TO AFTRFUNC ($A6AB) LOCATED
;IN THE FMDRIVER ROUTINE ($A6A8).
*=================================
* SUBROUTINE TO FREE UP A SECTOR
* IN A TRKMAP OF THE VTOC.
*=================================
FREESEC SEC ;SET CARRY SO FREE UP PRESENT SEC
;WHEN START ROTATING ASSIGNMENT
;MAP.
JSR SUB2FREE ;ADJUST ASSIGNMENT MAP TO FREE UP
;SEC BY SETTING BIT CORRESPONDING
;TO SEC #. NEXT, MERGE ASIGNMAP
;WITH THE APPROP BIT MAP IN VTOC.
LDA #0 ;ZERO OUT ASIGNSEC, ASIGNTRK
LDX #5 ;& ASIGNMAP (6 BYTES) IN WRK AREA
RELEASEC STA ASIGNSEC,X
DEX
BPL RELEASEC
RTS
*=================================
* CATALOG FUNCTION HANDLER.
*=================================
FNCATLOG JSR ZWRKAREA ;INITIALISE THE FM WORK AREA.
LDA #$FF ;ALLOW ANY VOL TO BE CATALOGED.
STA VOLWA ;(WHEN RWTS LATER ENTERED, THIS
;VALUE IS EORED WITH #$FF TO
;SIMULATED A COMPLEMENTED VOL #
;OF 0 (IE. #$FF EOR #$FF = #$00).
;AFTER RWTS READS THE ADDRESS
;CHECKSUM, IT CHECKS 2 SEE IF THE
;CORRECT VOL # WAS READ OFF THE
;DISK. IF THE COMPLEMENT OF THE
;VOL # IS 0, OR IF IT MATCHES THE
;VOL # READ OFF DSK, EXECUTION
;PROCEEDS AS IF THE CORRECT VOL
;WAS FOUND.)
JSR READVTOC ;READ VOLUME TABLE OF CONTENTS.
LDA #22 ;SET INDEX TO ALLOW 22 SCREEN
STA SCRNSRCH ;LINES BETWEEN PAUSES.
* PRINT 2 <CR>'S & THE WORDS
* "DISK VOLUME".
JSR CRCATLOG ;PRT <CR> & TEST IF PAUSE NEEDED.
JSR CRCATLOG ;DO IT AGAIN.
LDX #11 ;12 CHARS TO PRT (11 TO 0).
PRDSKVOL LDA DSKVOLUM,X ;GET CHAR OF REVERSE STRING.
JSR COUT ;PRINT CHAR.
DEX
BPL PRDSKVOL ;MORE CHARS IN STRING.
STX A5L+1 ;NONSENSE INSTRUCTION (CAUSE THE
;HI BYTE IS NOT USED IN THE
;PRVOLNMB ROUTINE ($AE42).)
LDA IBSMOD ;GET VOL# FOUND (FROM RWTS'S IOB)
STA A5L ;AND PUT IT IN A5L.
JSR PRVOLNMB ;GO PRINT VOL # (BUGGY ROUTINE).
JSR CRCATLOG ;PRT <CR> & TEST IF PAUSE NEEDED.
JSR CRCATLOG ;DO IT AGAIN.
* READ DIRECTORY SECTOR INTO THE
* DIRECTORY SECTOR BUFFER.
CLC ;(C)=0, READ 1RST DIR SEC.
;(C)=1, READ NEXT DIR SEC.
RDDIRSEC JSR RDDIRECT ;GO READ DIRECTORY SECTOR.
BCS TOFMXTOK ;RAN OUT OF DIR SECS SO GO EXIT.
LDX #0 ;INITIALIZE INDEX INTO DIR SEC.
* ANALYZE THE TRACK NUMBER.
DESCRPTK STX CURDIRNX ;SAVE NDEX TO ENTRIES IN DIR SEC.
LDA FIL1TSTK,X ;TRK # OF FILE'S 1RST T/S LIST
;(FROM THE FILE'S DESCRIPTION IN
;THE DIRECTORY SECTOR).
BEQ TOFMXTOK ;TRK # = 0, SO NO MORE ENTRIES IN
;CURRENT DIRECTORY BUFFER.
BMI NXDESCRP ;TRK#=$FF=DELETED FILE SO SKIP IT
* CHK FILE STATUS & PRINT LOCKED
* SYMBOL ("*") OR SPACE.
LDY #" " ;DEFAULT (Y)=<SPC> N CASE NOT LCK
LDA FIL1TYPE,X ;GET FILE TYPE.
BPL PRLOCODE ;HI BIT CLR SO FILE UNLOCKED.
LDY #"*" ;RESET (Y) = LOCKED SYMBOL.
PRLOCODE TYA ;EITHER PRINT "*" OR <SPC>.
JSR COUT
* PRINT CHAR CODE FOR FILE TYPE &
* A TRAILING <SPC>.
LDA FIL1TYPE,X ;GET FILE TYPE AGAIN & MAKE SURE
AND #$7F ;HI BYTE IS OFF SO CAN INDEX TBL
;THAT CONTAINS SYMBOLS FOR TYPES.
LDY #7 ;SET (Y) TO INDICATE 7 RELEVANT
;BITS AFTER SHIFT OUT HI BIT.
ASL ;THROW AWAY HI BIT.
CHRTYPIX ASL ;SHIFT REST OF BITS UNTIL HI SET.
BCS PRTFTYPE ;# OF SHIFTS 2 SET (C) DESIGNATES
;INDEX TO TYPE CHAR TABLE.
DEY ;REDUCE COUNT OF SHIFTS.
BNE CHRTYPIX ;NO SET BITS ENCOUNTERED YET, SO
;GO BACK TO DO MORE SHIFTS.
PRTFTYPE LDA FTYPETBL,Y ;GOT A SET BIT SO NOW GET CHAR
;FROM TABLE OF TYPE SYMBOLS.
JSR COUT ;PRINT TYPE SYMBOL.
LDA #" " ;PRINT TRAILING <SPC>.
JSR COUT
* PRINT FILE SIZE (EXPRESSED IN
* TERMS OF SECTORS).
LDA FIL1SIZE,X ;GET LOW & HI BYTES OF FILE SIZE
STA A5L ;(IN SECTORS) FROM FILE DESCRIP
LDA FIL1SIZE+1,X ;IN CUR DIR SEC & STICK THEM IN
STA A5L+1 ;IN A5L/H.
JSR PRVOLNMB ;PRINT FILE SIZE.
;*** NOTE *** - ROUTINE IS BUGGY.
;(DOESN'T USE HI BYTE, SO FILES
;> 255 SECS LONG ARE EXPRESSED
;AS 256 MOD.)
LDA #" " ;PRINT <SPC> AFTER SIZE.
JSR COUT
* PRINT THE FILE NAME.
INX ;KICK (X) UP CAUSE NAME STARTS AT
INX ;4TH BYTE FROM START OF FILE
INX ;DESCRIPTION ENTRY.
LDY #29 ;COUNTER FOR 30 CHRS/NAME (0-29).
PRTFNAME LDA FIL1TSTK,X ;GET CHR 4 FILE NAME & PRINT IT.
JSR COUT ;(P.S. BECAUSE THE OUTPUT HOOK
;STILL PTS TO DOS'S OUTPUT HNDLR,
;CTRL-D AND A SUBSUBSEQUENT DOS
;CMD CAN BE EMBEDDED IN THE FILE
;NAME AS A PROTECTION SCHEME.)
INX ;KICK UP INDEX INTO FILE DESCRIP.
DEY ;REDUCE THE CHARACTER COUNTER.
BPL PRTFNAME ;BRANCH IF MORE CHARS TO PRT.
JSR CRCATLOG ;PRT <CR> AFTR NAME, TEST 4 PAUS.
* KICK UP INDEX INTO CURRENT DIRECTORY
* SECTOR BUF TO PT AT START OF NEXT
* FILE DESCRIPTION ENTRY.
NXDESCRP JSR NXPLUS35 ;ADD 35 BYTES TO INDEX SO IT PTS
;TO NEXT ENTRY IN CURRENT DIR SEC.
BCC DESCRPTK ;(C) = 0, SO GO LOOK FOR MORE
;ENTRIES IN THIS PARTICULAR
;DIRECTORY SECTOR.
BCS RDDIRSEC ;(C) = 1, SO THERE AREN'T MORE
;ENTRIES IN THIS DIRECT SECTOR.
;THERE4, GO BACK TO READ IN
;ANOTHER DIRECTORY SECTOR.
*=================================
* EXIT FILE MANAGER CLEANLY.
*=================================
TOFMXTOK JMP GOODFMXT ;EVENTUALY RETURNS TO AFTRFUNC
;($A6AB) LOCATED IN THE FMDRIVER
;ROUTINE ($A6A8).
*=================================
* PRINT <CR> & CHK FOR PAUSE.
*=================================
CRCATLOG LDA #$8D ;PRINT A <CR>.
JSR COUT
DEC SCRNSRCH ;DEC INDEX 2 SEE IF PAUSE NEEDED.
BNE CRCATRTN ;PAUSE NOT REQUIRED.
JSR RDKEY ;PAUSE SO INFO CAN BE ABSORBED
LDA #21 ;BEFORE SCROLLED OFF SCRN.
STA SCRNSRCH ;RESET INDEX FOR FRESH SCRN INFO.
CRCATRTN RTS
*=================================
* CONVERT 1 HEX BYTE TO 3-DIGIT
* DECIMAL (WITH LEADING ZEROES IF
* APPLICABLE).
*=================================
* NOTE: THIS IS A BUGGY ROUTINE
* - DOESN'T USE HI BYTE SO NUMBERS
* GREATER THAN 255 ARE EXPRESSED
* AS 256 MOD.
*
* (PS. TO USE AS A STAND-ALONE
* ROUTINE, LOAD A5L WITH HEX & CALL
* PRVOLNMB. DESTROYS (A) & (Y) REGS.
* CONVERSION DONE BY SIMULATING
* DIVISION VIA SUCCESSIVE SUBTRACTIONS
* OF POWERS OF 10.)
PRVOLNMB LDY #2 ;INDEX TO # OF CONVERSION FACTORS
;AND DIGITS.
ZONSTK LDA #0 ;INIT COUNT OF # OF SUBTR'S DONE.
PHA ;SAVE COUNT ON STACK.
GETVNMB LDA A5L ;GET LOW BTE HEX AND CMP IT TO
CMP BASETEN,Y ;TABLE OF CONVERSION FACTORS.
;CONVERSION TABLE CONTAINS POWERS
;OF 10: 10^2=100, 10^1=10, 10^0=1
BCC TONEGASC ;BRANCH IF # < 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 OF # OF SUBT'S AND
ADC #0 ;ADD (C). IF REMAIN. > CONVERSION
PHA ;FACTOR, ADD 1, ELSE ADD NOTHING.
JMP GETVNMB ;GO BACK TO DO MORE SUBT'S WITH
;SAME CONVERSION FACTOR.
TONEGASC PLA ;GET RESULT OF DIV (IE. WHOLE #
;OF SUBTRACTIONS).
ORA #$B0 ;CONVERT COUNT TO NEG ASCII CHAR.
JSR COUT ;PRT CHAR.
DEY ;3 CHARS/VOL# (IE. 2 TO 0).
BPL ZONSTK ;(3 CONVERSION FACTORS.)
RTS
*=================================
* COPY CONTENTS OF FM WORK BUFFER
* (IN DOS CHAIN) TO FM WORK AREA
* (NOT IN DOS CHAIN).
*=================================
RSTRFMWA JSR SELWKBUF ;PT A4L/H AT FM WORK BUF.
;(GET ADR FRM FM PARAMETER LIST.)
LDY #0 ;ZERO OUT RETURN CODE IN FM PARM
STY RTNCODFM ;LIST TO SIGNAL NO ERORS.
STORFMWK LDA (A4L),Y ;COPY FM WORK BUF 2 FM WORK AREA.
STA FMWKAREA,Y
INY
CPY #45 ;45 BYTES TO COPY (0 TO 44).
BNE STORFMWK
CLC ;WHY?????
RTS
*=================================
* COPY FM WORK AREA TO FM WORK BUF
* (LOCATED IN CHAIN OF DOS BUFS).
*=================================
CPYFMWA JSR SELWKBUF ;PT A4L/H AT FM WORK BUF (CHAIN).
;(GET ADR FROM FM PARM LIST.)
LDY #0 ;INITIALIZE INDEX.
STORWRK LDA FMWKAREA,Y ;COPY WORK AREA -----> WORK BUF.
STA (A4L),Y
INY
CPY #45 ;45 BYTES TO COPY (0 TO 44).
BNE STORWRK
RTS
*=================================
* INIT FUNCTION HANDLER.
*=================================
FNINIT JSR ZWRKAREA ;INIT THE FM WRK AREA (NON-CHAIN)
LDA #4 ;OPCODE FOR FORMAT.
* GO FORMAT THE DISK.
JSR RWTSDRV1 ;CALL RWTS DRIVER TO FORMAT DISK.
* PUT VOL#, # OF NEXT TRK TO BE
* ASSIGNED & ASSIGNMENT DIRECTION
* IN THE VTOC SECTOR BUFFER.
LDA VOLWA ;COMPLEMENTED VOL# (FRM WRK AREA)
EOR #$FF ;UNCOMPL. IT & PUT VOL# IN VTOC.
STA VOLUSED
LDA #$11 ;USE TRK # 17 FOR CATALOG TRK.
STA NXTRKUSE ;SET CAT TRK AS NXT TRK TO ALLOC.
;(NXTRKUSE IS LOCATED IN VTOC.)
LDA #1 ;ALLOCATION DIRECTION = FORWARD.
STA DRECTION
* ZERO OUT VTOC FROM TRKMAP0 TO
* END OF SECTOR. (NOTE: THIS
* ASSIGNS ALL TRACKS.)
LDX #56 ;OFFSET INTO VTOC TO TRKMAP0.
LDA #0
ZVTOC STA VTOCBUFF,X ;ZERO OUT A TRKMAP BYTE.
INX
BNE ZVTOC
* FREE UP ALL TRKS EXCEPT TRKS 0,
* 1, 2 & CAT TRK (#17).
*
* NOTE: DOS ONLY OCCUPIES SECTORS
* 0 TO 4 ON TRK 2, BUT ROUTINE
* TAKES REST OF SECS ON TRK 2 OUT
* OF CIRCULATION.
LDX #$0C ;OFFSET TO START OF TRKMAP3.
FREETRK CPX #$8C ;OFFSET 1 PAST END OF TRKMAP34.
BEQ FREEDTKS ;DONE UP TO END OF TRKMAP34.
LDY #3 ;INIT INDEX TO END OF FRETKMSK.
FREEIT LDA FRETKMSK,Y ;FREE MOST TRKMAPS. (STARTING
;WITH TRKMAP3).
;NOTE: NOT FREEING UP VTOC SEC
;OR TRKS USED BY DOS.
STA TRKMAP0,X ;FREE TRKS BY PLACING FOLLOWING
;BYTES IN @ TRKMAP: "FF FF 00 00"
INX ;KICK UP INDEX TO BYTE IN TRKMAP.
DEY ;REDUCE INDEX TO FRETKMSK CAUSE
;LOADING FROM END OF FRETKMSK:
; "00 00 FF FF".
BPL FREEIT ;(4BYTES/TRKMAP & 4BYTS/FRETKMSK)
CPX #$44 ;OFFSET TO START OF TRKMAP17
;(IE. CATALOG TRACK).
BNE FREETRK ;HAVE WE FREED TRKS 3 TO 16 YET?
;IF NOT - BRANCH.
LDX #$48 ;OFFSET TO TRK 18 (IE. SKIP THE
;CATALOG TRACK).
BNE FREETRK ;ALWAYS - GO FREE TRKS 18 TO 34.
FREEDTKS JSR WRITVTOC ;WRITE FREED UP VTOC TO DISK.
* CLEAR OUT THE DIRECTORY SEC BUF.
LDX #0
TXA
CLRDIREC STA DIRECBUF,X
INX
BNE CLRDIREC
JSR PT2DIRBF ;DESIGNATE DIR SEC BUF AS I/O BUF
LDA #$11 ;(A) = # OF CAT TRK.
LDY SECPERTK ;# OF SECS/TRK = 16.
DEY
DEY
STA IBTRK ;PUT CAT TRK IN IOB.
* WRITE DIRECTORY SECS (TRK17,
* SECS 15 TO 1) TO DISK.
SETLNKTK STA DIRLNKTK ;SET TRK/SEC VALS FOR LINK 2 NEXT
SETLNKSC STY DIRLNKSC ;DIRECTORY SECTOR.
INY ;GET SEC # TO WRITE & PUT IT IN
STY IBSECT ;RWTS'S IOB.
LDA #2 ;WRITE OPCODE.
JSR RWTSDRV1 ;WRITE DIRECTORY SEC TO DISK.
LDY DIRLNKSC ;SEC VAL OF NEXT DIR SEC 2 WRITE.
DEY ;KICK IT DWN (WILL INC IT LATER).
BMI DOIMAGE ;DON'T DO SEC 0 CAUSE THAT'S VTOC
BNE SETLNKSC ;GO WRITE SECS 2 TO 15.
TYA
BEQ SETLNKTK ;GO BACK TO WRITE SEC 1 AND ZERO
;OUT THE DIRECTORY SECTOR LINKS.
* ROUTINE TO WRITE THE DOS
* IMAGE ON TRACKS 0 TO 2.
DOIMAGE JSR PRPWRDOS ;GET READY TO WRITE DOS IMAGE.
JSR WRDOSIMG ;WRITE DOS IMAGE TO DISK.
JMP GOODFMXT ;EXIT FM CLEANLY. EVENTUALLY RTNS
;TO AFTRFUNC ($A6AB) LOCATED IN
;THE FMDRIVER ROUTINE ($A6A8).
*=================================
* POINT A4L/H AT A SPECIFIC
* SECTION OF A DOS BUFFER.
*=================================
SELWKBUF LDX #0 ;SELECT WORK BUFFER.
BEQ PT2FMBUF ;ALWAYS.
SELTSBUF LDX #2 ;SELECT T/S LIST BUFFER.
BNE PT2FMBUF ;ALWAYS.
SELDABUF LDX #4 ;SELECT DATA BUFFER.
PT2FMBUF LDA WRKBUFFM,X ;GET ADDR OF SELECTED BUF FROM
STA A4L ;FM PARM LST & PUT IT IN POINTER.
LDA WRKBUFFM+1,X
STA A4L+1
RTS
*=================================
* CHK IF DATA SEC BUF HAS CHANGED
* SINCE LAST READ OR WRITE.
*=================================
CKDATUP BIT UPDATFLG ;CHK BIT6 SO SEE IF CHANGED.
BVS WRITDATA ;TAKE BRANCH IF CHANGED.
RTS
*=================================
* WRITE PRESENT DATA SECTOR BUFFER
* TO THE DISK. (UPDATES DISK SO
* CAN READ IN NEXT DATA SEC WITH-
* OUT OVERWRITING AND THEREFORE
* LOSING PREVIOUS DATA.)
*---------------------------------
WRITDATA JSR PRPDAIOB ;PREPARE RWTS'S IOB FOR WRITING
;DATA SEC BUF TO DISK.
LDA #2 ;OPCODE FOR WRITE CMD.
JSR RWTSDRVR ;CALL DRIVER 2 WRT DATA SEC BUF.
LDA #%10111111 ;SHUT BIT6 OFF IN UPDATE FLAG TO
AND UPDATFLG ;SIGNAL THAT THE DATA SECTOR BUF
STA UPDATFLG ;IS UP TO DATE.
RTS
*===================================
* CHK IF T/S LIST REQUIRES UPDATING.
* (HAS T/S LIST BUF CHANGED SINCE
* LAST READ OR WRITE?)
*===================================
CKTSUPDT LDA UPDATFLG
BMI WRITETS ;IF BIT7 SET, UPDATING REQUIRED.
RTS
*=================================
* UPDATE T/S LIST SEC BUF ON DISK.
*---------------------------------
WRITETS JSR SETTSIOB ;PREPARE RWTS'S IOB FOR WRITING
;T/S LIST BUFFER TO DISK.
LDA #2 ;RWTS'S WRITE OPCODE.
JSR RWTSDRVR ;CALL RWTS DRIVER 2 WRITE T/S LST
LDA #$7F ;CLR BIT7 OF UPDATE FLAG 2 SIGNAL
AND UPDATFLG ;THAT T/S LIST IS UP TO DATE.
STA UPDATFLG
RTS
*=================================
* PREPARE RWTS'S IOB FOR READING
* OR WRITING T/S LIST SEC.
*=================================
SETTSIOB LDA TSBUFFM ;GET ADR OF T/S LIST BUF FROM
STA IBBUFP ;FM PARM LIST & DESIGNATE AS I/O
LDA TSBUFFM+1 ;BUF IN RWTS'S IOB.
STA IBBUFP+1
LDX CURTSTRK ;SET (X)/(Y) = TRK/SEC OF CURRENT
LDY CURTSSEC ;T/S LIST SECTOR.
RTS
*=================================
* READ T/S LIST SEC TO BUFFER.
*=================================
READTS PHP ;SAVE CARRY ON STK.
;(C)=0=READ 1RST T/S LIST SEC.
;(C)=1=READ NEXT T/S LIST SEC.
JSR CKTSUPDT ;WRITE T/S LIST SEC BUF IF
;UPDATING REQUIRED. (IF T/S LST
;BUF HAS CHANGED SINCE LAST READ
;OR WRITE, THEN WRITE IT BACK TO
;DISK SO DON'T OVERWRITE BUF AND
;LOSE INFO WHEN RD NEW T/S LIST.)
JSR SETTSIOB ;PREP RWTS'S IOB FOR READING T/S
;LIST SEC.
JSR SELTSBUF ;POINT A4L/H AT T/S LIST BUF.
;(GETS ADR FROM FM PARM LIST.)
PLP ;GET SAVED (C) BACK FROM STK.
BCS RDNXTTS ;IF (C)=1, ALREADY READ 1RST T/S
;LIST SEC, SO GO READ NEXT ONE.
* READ 1RST T/S LIST SEC.
* (CARRY WAS CLR.)
RDFIRSTS LDX FIRSTSTK ;SET (X)/(Y)=TRK/SEC OF 1RST T/S
LDY FIRTSSEC ;LIST SECTOR.
JMP RDTSLST ;GO READ T/S LIST SEC INTO BUF.
* ---
* READ NEXT T/S LIST SEC.
* (CARRY WAS SET.)
RDNXTTS LDY #1 ;INDEX INTO T/S LIST BUF.
LDA (A4L),Y ;TRK FOR LNK 2 NEXT T/S LIST SEC.
BEQ TSLNKZRO ;LINK ZEROED OUT SO NO MORE
;T/S LIST SECS FOR FILE.
TAX ;(X) = NEXT T/S LIST TRK.
INY
LDA (A4L),Y ;SEC# FOR LNK 2 NXT T/S LIST SEC.
TAY ;(Y) = NEXT T/S LIST SEC.
JMP RDTSLST ;GO READ NEXT T/S LIST SEC IN.
* ---
* T/S LINK ZEROED OUT SO
* DECIDE IF ERROR OR NOT.
TSLNKZRO LDA OPCODEFM ;CHK R/W STATUS TO SEE IF WANT TO
CMP #4 ;ADD ANOTHER T/S LIST.
BEQ UPDATETS ;WRITING - GO UPDATE LINK.
SEC ;WERE READING & LNK ZEROED OUT,
RTS ;SO RTN WITH (C)=1 SO GENERATE AN
* === ;ERROR. (REMEMBER, PREVIOUSLY SET
;RTN CODE TO A DEFAULT VALUE FOR
;FILE-NOT-FOUND.) HOWEVER, IF
;READING IS BEING DONE FOR AN
;APPEND OR VERIFICATION, THEN THE
;SET (C) JUST DENOTES THAT HAVE
;REACHED THE END OF THE FILE.
* WRITING & LNK ZEROED OUT SO MUST
* ALLOCATE A NEW T/S LIST SECTOR.
UPDATETS JSR ASGNTKSC ;FIND & RESERVE TRK/SEC VALS FOR
;A NEW T/S LIST SECTOR.
* LINK THE NEW T/S LIST SECTOR TO
* THE LAST T/S LIST SECTOR AND
* THEN WRITE THE UPDATED VERSION
* OF THE LAST T/S LIST SECTOR TO
* THE DISK.
LNKOLDNW LDY #2 ;OFFSET TO SEC# LINK BYTE.
STA (A4L),Y ;PUT NEW SEC VAL IN LINK AND THEN
PHA ;SAVE IT ON STK.
DEY ;OFFSET TO TRK BYTE OF LINK.
LDA ASIGNTRK ;PUT NEW TRK VAL IN LINK.
STA (A4L),Y
PHA ;SAVE TRK VAL ON STK.
JSR WRITETS ;WRITE UPDATED T/S LIST TO DISK.
* SET UP A BRAND NEW T/S LIST
* SECTOR & WRITE IT TO DISK.
ZOUTTS JSR ZCURBUF ;ZERO OUT T/S LIST BUF.
LDY #5 ;AT OFFSETS 5 & 6 IN2 THE NEW T/S
LDA RELASTP1 ;LIST, PUT REL SEC # PLUS 1 (IN
STA (A4L),Y ;RELATION TO THE ENTIRE FILE) OF
INY ;THE 1RST DATA PAIR THAT WILL BE
LDA RELASTP1+1 ;DESCRIBED IN THIS NEW T/S LIST.
STA (A4L),Y ;(POSSIBLE VALUES ARE: $007A,
;2*$007A, 3*$007A AND 4*$007A.
PLA ;GET (X)/(Y)=TRK/SEC VALS 4 THIS
TAX ;NEW T/S LIST SEC OFF STACK.
PLA
TAY
LDA #2 ;WRITE OPCODE FOR RWTS.
BNE RDWRTS ;ALWAYS - GO WRITE T/S LIST SEC.
* ---
* SUBROUTINE TO READ T/S LIST SEC.
RDTSLST LDA #1 ;READ OPCODE FOR RWTS.
* COMMON TO READ/WRITE T/S LIST.
RDWRTS STX CURTSTRK ;NEW T/S LIST SECTOR TRK/SEC VALS
STY CURTSSEC ;BECOME CURRENT TRK/SEC VALS.
JSR RWTSDRVR ;CALL RWTS DRIVER 2 READ OR WRITE
;THE CURRENT T/S LIST SECTOR.
* UPDATE FM WORK AREA BUF (NON-CHAIN).
LDY #5 ;OFFSET IN2 CURRENT T/S LIST BUF.
LDA (A4L),Y ;STORE REL SEC # OF 1RST DAT PAIR
STA RELFIRST ;THAT CAN BE DESCRIBED IN THIS
;T/S LIST. (POSSIBLE VALUES ARE:
;$0000, $007A, 2*$007A, 3*$007A
;AND 4*$007A.)
CLC ;ADD THE MAXIMUM # OF DATA SECS
ADC MXSCURTS ;THAT CAN POSSIBLY BE DESCRIBED
;IN THIS T/S LIST.
STA RELASTP1 ;STORE THE MAXIMUM RELATIVE SEC #
INY ;(PLUS 1) OF THE LAST DATA PAIR
;THAT CAN POSSIBLY BE DESCRIBED
;IN THIS T/S LIST.
LDA (A4L),Y
STA RELFIRST+1
ADC MXSCURTS+1
STA RELASTP1+1 ;(RELASTP1/+1 IS ALWAYS SET TO
;$007A BY FNOPEN. (POSSIBLE VALS
;ARE: $007A, 2*$007A, 3*$007A,
;4*$007A OR 5*$007A.)
CLC ;RETURN WITH NO ERRORS SIGNAL.
RTS
*=================================
* READ DATA SEC TO DATA SEC BUF.
*=================================
READDATA JSR PRPDAIOB ;SET UP RWTS'S IOB 2 RD DATA SEC.
LDA #1 ;READ OPCODE FOR RWTS.
JMP RWTSDRVR ;CALL RWTS DRIVER 2 READ DAT SEC.
*=================================
* PREP RWTS'S IOB TO READ
* OR WRITE THE DATA SECTOR.
*==================================
PRPDAIOB LDY DATBUFFM ;GET ADR OF DATA SEC BUF FROM THE
LDA DATBUFFM+1 ;FM PARM LIST & DESIGNATE IT AS
STY IBBUFP ;THE I/O BUF FOR RWTS'S IOB.
STA IBBUFP+1
LDX CURDATRK ;ENTER RWTS DRIVER WITH (X)/(Y)
LDY CURDATSC ;CONTAINING THE TRK/SEC VALUES OF
RTS ;THE DATA SECTOR.
$

View File

@@ -0,0 +1,907 @@
*=================================
* READ THE VOLUME TABLE
* OF CONTENTS (VTOC).
*=================================
READVTOC LDA #1 ;READ OPCODE FOR RWTS.
BNE RDWRVTOC ;ALWAYS.
*=================================
* WRITE VOLUME TABLE
* OF CONTENTS (VTOC).
*---------------------------------
WRITVTOC LDA #2 ;WRITE OPCODE FOR RWTS.
* COMMON TO READ/WRITE VTOC.
RDWRVTOC LDY ADRVTOC ;GET ADR OF VTOC FRM FM CONSTANTS
STY IBBUFP ;TABLE & DESIGNATE IT AS THE I/O
LDY ADRVTOC+1 ;BUF IN RWTS'S IOB.
STY IBBUFP+1
LDX TRKWA ;ENTER RWTS DRIVER WITH (X)/(Y)
LDY #0 ;EQUAL TO TRK/SEC VALS OF VTOC.
JMP RWTSDRVR ;CALL DRIVER TO READ/WRITE VTOC.
*=================================
* READ A DIRECTORY SECTOR.
*=================================
RDDIRECT PHP ;SAVE (C) ON STK:
; (C) = 0 = READ 1RST DIR SEC.
; (C) = 1 = READ NEXT DIR SEC.
JSR PT2DIRBF ;DESIGNATE DIR SEC BUF AS I/O BUF
;IN RWTS'S IOB.
PLP ;CHK IF DEALING WITH 1RST DIR SEC
BCS RDNXTDIR ;NO - GO READ NEXT DIR SEC.
* READ THE FIRST DIRECTORY SECTOR.
* (C) = 0
RDFIRDIR LDY FIRDIRSC ;(Y)/(X)=TRK/SEC VALS OF 1RST
LDX FIRDIRTK ;DIRECTORY SEC (FROM VTOC BUF).
BNE DODIRRD ;ALWAYS - GO READ IN DIREC SEC.
* READ THE NEXT DIRECTORY SECTOR.
* (C) = 1
RDNXTDIR LDX DIRLNKTK ;GET TRK OF NXT DIR SEC FROM LINK
;IN CURRENT DIRECTORY SECTOR.
BNE GETDIRLK ;LINK NOT ZEROED OUT.
SEC ;LINK ZEROED OUT -EXIT WITH (C)=1
RTS ;TO SIGNAL NO MORE DIREC SECS.
* ===
GETDIRLK LDY DIRLNKSC ;GET SEC OF NEXT DIR SEC FRM LINK
;BYTES IN CURRENT DIRECTORY SEC.
* CALL TO READ IN DIRECTORY SECTOR.
DODIRRD STX CURDIRTK ;SAV TRK/SEC VALS OF DIRECTORY WE
STY CURDIRSC ;ARE ABOUT 2 READ SO THEY WILL BE
;THE CURRENT DIRECTORY SEC VALS
;FOR THE NEXT TIME AROUND.
LDA #1 ;READ OPCODE FOR RWTS.
JSR RWTSDRVR ;CALL RWTS DRIVER TO DO THE READ.
CLC ;LINK DIDN'T ZERO OUT SO SIGNAL
RTS ;MORE DIREC SECS EXIST & THEN XIT
*=================================
* WRITE THE DIRECTORY BUFFER.
*=================================
WRDIRECT JSR PT2DIRBF ;DESIGNATE DIREC SEC BUF AS I/O
;BUF IN RWTS'S IOB.
LDX CURDIRTK ;ENTER RWTS DRIVER WITH (X)/(Y)
LDY CURDIRSC ;EQUAL TO THE TRK/SEC VALS OF THE
;DIRECTORY SECTOR.
LDA #2 ;WRITE OPCODE FOR RWTS.
JMP RWTSDRVR ;CALL DRIVER TO WRITE DIREC SEC.
*==================================
* DESIGNATE DIRECTORY SECTOR BUFFER
* AS I/O BUFFER IN RWTS'S IOB.
*==================================
PT2DIRBF LDA ADRDIRBF ;GET ADDR OF DIREC SEC BUF FROM
STA IBBUFP ;FM CONSTANTS TBL & DESIGNATE IT
LDA ADRDIRBF+1 ;AS I/O BUFFER IN RWTS'S IOB.
STA IBBUFP+1
RTS
*==================================
* READ/WRITE TRACK/SECTOR DRIVERS.
*==================================
RWTSDRVR STX IBTRK ;ENTER WITH (X) = TRK WANTED.
STY IBSECT ; (Y) = SEC WANTED.
RWTSDRV1 STA IBCMD ; (A) = OPCODE FOR RWTS
;RWTSDRV1 = ENTRY PT USED BY INIT
;FUNCTION HNDLR WHEN FORMATTING.
CMP #2 ;IS CMD A WRITE? NOTE: THE "CMP"
;CONDITIONS THE CARRY AS FOLLOWS:
;(C)=0 =SEEK ($00) OR READ ($01)
;(C)=1 =WRITE($02) OR FORMAT($03)
BNE SKPWRSET ;BRANCH IF NOT WRITING.
ORA UPDATFLG ;CONDITION UPDATE FLG 2 DESIGNATE
STA UPDATFLG ;LAST OPERATION WAS A WRITE (FOR
;NEXT TIME AROUND).
* FINISH SETTING UP RWTS'S
* INPUT/OUTPUT BLOCK (IOB).
SKPWRSET LDA VOLWA ;PUT COMPLEMENTED 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 SEC LENGTH IN IOB (STANDARD
STA IBSECSZ ;SIZE OF #256 OR $0100 BYTES).
LDA SECSIZWA+1
STA IBSECSZ+1
LDA #1
STA IBTYPE
LDY ADRIOB ;SET (Y) & (A) TO POINT AT
LDA ADRIOB+1 ;RWTS'S IOB.
*=================================
* CALL RWTS
*=================================
JSR ENTERWTS ;SAV STATUS,SET INTERRUPT DISABLE
;FLAG & CALL RWTS TO PERFORM TASK
;(SEEK, READ, WRITE, FORMAT).
LDA IBSMOD ;GET VOL FOUND (FRM IOB) & PUT IT
STA VOLFM ;IN THE FM PARAMETER LIST.
LDA #$FF ;PUT VOL WANTED IN IOB.
STA IBVOL ;(USE 255 AS DEFAULT VAL FOR NEXT
;TIME. ACTUALLY USING 0 CAUSE
;#$FF EOR #$FF = $00).
BCS ERRWTSDR ;OPERATION WAS UNSUCCESSFUL.
RTS ;ABOVE BRANCH NEVER TAKEN WHEN
;USING SEEK CMD, CAUSE NO ERROR
;CHKING ROUTINES ARE ENCOUNTERED
;BY A LONE SEEK OPERATION.
*=================================
* OPERATION WAS NOT SUCCESSFUL.
*=================================
ERRWTSDR LDA IBSTAT ;GET RWTS'S ERROR CODE.
* TRANSLATE RWTS ERROR CODE (A)
* TO FM ERROR CODE (Y). (DOS LATER
* EMPLOYS FM ERROR CODE IN ROUTINE
* USED TO PRINT ERROR MESSAGES.)
LDY #7 ;SET (Y) FOR FM ERROR CODE.
CMP #$20 ;VOL MISMATCH?
BEQ SETFMERR ;YES.
LDY #4 ;NO.
CMP #$10 ;WRITE PROTECTED?
BEQ SETFMERR ;YES.
LDY #8 ;NO - MUST HAVE BEEN OTHER SO
SETFMERR TYA ;DESIGNATE IT AS GENERAL I/O ERR.
JMP BADFMXIT ;GO HANDLE ERROR.
;ANY ERR ENCOUNTERED WHEN FORMAT-
;TING IS TREATED AS AN I/O ERROR.
*==========================================
* READ DATA SEC IF NECESSARY.
*==========================================
* CHECK IF NEED TO READ THE NEXT DATA
* SECTOR INTO THE DATA SECTOR BUFFER.
*
* - IS DATA SEC WE WANT ALREADY IN MEMORY?
* - IF SO, DOES IT REQUIRE UPDATING?
* IF THE SECTOR OFFSET INTO FILE (FILPTSEC)
* EQUALS THE RELATIVE SECTOR NUMBER OF THE
* LAST SECTOR READ OR WRITTEN (RELPREV),
* THEN THE SECTOR WE WANT IS PRESENTLY IN
* MEMORY. IF IT IS NOT IN MEMORY, READ IN
* THE DATA SECTOR WANTED. HOWEVER, FIRST
* CHECK IF THE DATA SECTOR HAS CHANGED
* SINCE THE LAST READ OR WRITE. IF IT HAS,
* THE DISK MUST BE UPDATED BEFORE WE READ
* IN THE NEW DATA SECTOR SO WE DON'T OVER-
* WRITE THE DATA SECTOR BUFFER AND LOOSE
* INFORMATION.
* NOTE: - IF THIS SUBROUTINE IS CALLED
* FROM A WRITE SUBFUNCTION AND
* FILPTSEC IS NOT EQUAL TO RELPREV,
* THEN THE DATA SECTOR BUFFER MUST
* BE FULL AND SHOULD BE WRITTEN
* TO THE DISK BEFORE ANY MORE
* INFORMATION IS READ IN.
* - IF THE FILE WAS JUST OPENED, THE
* OPEN SUBFUNC SET FILPTSEC=#$0000
* AND RELPREV=#$FFFF SO ALWAYS
* FORCE READING OF A NEW DATA SEC
* EVEN IF THE CORRECT SECTOR IS
* ALREADY IN MEMORY.
NXTDATRD LDA FILPTSEC ;LAST SEC USED VS CUR SEC WNTD.
CMP RELPREV
BNE CKWCURDA ;NOT SAME - WILL EVENTUALLY HAVE
;TO READ NEW DATA SEC IN.
LDA FILPTSEC+1 ;MAYBE SAME - CHK HI BYTES.
CMP RELPREV+1
BEQ XITNXDAT ;SAME SO GO EXIT.
*=====================================
* WRITE THE DATA SECTOR IF NECESSARY.
*-------------------------------------
* DATA SEC WE WANT IS NOT PRESENTLY IN
* MEMORY. CHK IF NEED TO WRITE THE
* CURRENT DATA SEC BUF BEFORE WE READ
* IN THE WANTED DATA SECTOR.
CKWCURDA JSR CKDATUP ;CHK UPDATE FLG 2 SEE IF DATA SEC
;BUF HAS CHANGED SINCE LAST R/W.
;IF IT HAS, WRITE DATA BUF 2 DSK.
* SHOULD THE CURRENT T/S LIST BE USED?
* (THAT IS, SHOULD THE DATA SECTOR BE
* LISTED IN THE PRESENT T/S LIST SECTOR?
* IF NOT, THEN WILL NEED TO READ IN THE
* CORRECT T/S LIST.)
* IS THE SECTOR OFFSET INTO THE FILE OF
* THE PRESENT DATA SECTOR LESS THAN THE
* RELATIVE SECTOR NUMBER OF THE FIRST
* DATA SECTOR THAT CAN BE DESCRIBED IN
* THE T/S LIST PRESENTLY IN MEMORY?
* (IF LESS, THEN NEED TO READ IN A
* DIFFERENT T/S LIST SECTOR.)
CKCURTS LDA FILPTSEC+1 ;SEC OFFSET INTO FILE ASSOCIATED
CMP RELFIRST+1 ;WITH THE PRESENT DATA SECTOR
;VERSUS THE RELATIVE SEC# OF THE
;FIRST DATA SEC DESCRIBED IN THE
;PRESENT T/S LIST.
BCC NEEDNXTS ;DATA SEC WANTED REPRESENTS A
;SMALLER OFFSET INTO FILE SO NEED
;A DIFFERENT T/S LIST.
BNE CKCURTS1 ;SEC OFFSET OF WANTED DATA SEC IS
;LARGER THAN THAT OF THE 1RST DAT
;SEC THAT CAN BE DESCRIBED IN THE
;PRESENT T/S LIST SO IT MAY STILL
;BELONG TO THIS T/S LIST.
LDA FILPTSEC ;HI BYTES SAME -SO CMP LOW BYTES.
CMP RELFIRST
BCC NEEDNXTS ;SEC OFFSET OF WNTD FILE IS LESS
;SO READ IN A DIFFERENT T/S LIST.
;(START BY READING THE FILE'S
;FIRST T/S LIST.)
* SECTOR OFFSET ASSOCIATED WITH THE DATA
* SECTOR WE WANT IS EITHER GREATER THAN
* OR EQUAL TO THE RELATIVE SECTOR OFFSET
* ASSOCIATED WITH THE FIRST DATA SECTOR
* THAT CAN BE DESCRIBED IN THIS T/S LIST.
* THEREFORE, COMPARE THE SECTOR OFFSET
* OF THE SECTOR WANTED WITH THE RELATIVE
* SECTOR NUMBER (PLUS 1) OF THE LAST
* SECTOR THAT CAN BE DESCRIBED IN THE
* PRESENT T/S LIST.
CKCURTS1 LDA FILPTSEC+1 ;SEC OFFSET OF DATA SEC WANTED
CMP RELASTP1+1 ;VS RELATIVE SEC # OF THE LAST
;DATA SEC THAT CAN POSSIBLY BE
;DESCRIBED IN THE PRES T/S LIST.
BCC GETDATPR ;SEC OFFSET ASSOC WITH DATA SEC
;WANTED IS DESCRIBED IN THE
;PRESENT T/S LIST.
BNE NEEDNXTS ;SEC OFFSET OF PRESENT DATA SEC
;IS LARGER THAN THAT OF THE LAST
;DATA SECTOR (PLUS 1) THAT CAN
;POSSIBLY BE DESCRIBED IN THE
;PRESENT T/S LIST, SO WE NEED A
;NEW T/S LIST SECTOR.
LDA FILPTSEC ;HI BYTES SAME -SO CMP LOW BYTES.
CMP RELASTP1
BCC GETDATPR ;SEC OFFSET ASSOCIATED WITH THE
;DATA SECTOR WE WANT IS LESS THAN
;THE RELATIVE SEC # (PLUS 1) OF
;THE LAST DATA SECTOR THAT CAN
;POSSIBLY BE LISTD IN THE PRESENT
;T/S LIST. (THERE4, THE WANTED
;DATA SEC SHOULD BE DESCRIBED IN
;THE PRESENT T/S LIST.)
* THE DATA SECTOR WE WANT IS NOT
* LISTED IN THE PRESENT T/S LIST,
* SO WE MUST READ A DIFFERENT T/S
* LIST SECTOR. (NOTE: ROUTINE IS
* ENTERED WITH (C) = 1 IF NEED A
* HIGHERED NUMBERED T/S LIST.
* IF (C) = 0, THEN THE FILE POINTER
* WAS BACKED UP AND WE NEED A SMALLER
* NUMBERED T/S LIST.)
NEEDNXTS JSR READTS ;READ IN THE NEXT (OR FIRST) T/S
;LIST. HOWEVER, FIRST CHECK THE
;UPDATE FLAG TO SEE IF THE T/S
;LST PRESENTLY IN MEMORY REQUIRES
;UPDATING BEFORE WE READ IN THE
;NEXT (OR FIRST) T/S LIST SECTOR.
;IF UPDATING IS REQUIRED, WRITE
;THE PRESENT T/S LIST.
BCC CKCURTS ;GO BACK & CHK IF THIS IS CORRECT
;T/S LIST.
RTS ;RTN WITH (C)=1 TO SIGNAL THAT WE
* === ;RAN OUT OF T/S LISTS WHILE
;READING OR TO DO GOOD EXIT IF
;RAN OUT OF DATA WHILE VERIFYING
;OR 2 SIGNAL POSSIBLE ERROR WHILE
;APPENDING.
* KNOW DATA SEC SHOULD BE DESCRIBED
* IN PRESENT T/S LIST SO NOW CALC
* OFFSET INTO T/S LIST WHERE DATA
* PAIR SHOULD BE LOCATED.
GETDATPR SEC ;CALC OFFSET TO DATA PAIR:
LDA FILPTSEC ;SEC OFFSET OF DATA SEC INTO FILE
SBC RELFIRST ;MINUS REL INDEX OF 1RST DATA SEC
;DESCRIBED IN PRES T/S LIST.
ASL ;TIMES 2 CAUSE 2 BYTES USED TO
;DESCRIBE A DATA PAIR.
ADC #12 ;ADD 12 CAUSE 1RST DATA PAIR IS
TAY ;ALWAYS LISTED 12 BYTES FROM THE
;START OF THE T/S LIST BUFFER.
JSR SELTSBUF ;POINT A4L/H AT THE T/S LIST BUF.
LDA (A4L),Y ;GET TRK # OF DATA SEC PAIR.
BNE RDDATSEC ;GO READ IN THE DATA SECTOR.
* THE TRK# PART OF THE DATA SECTOR
* PAIR LISTED IN THE T/S LIST WAS
* ZERO. THEREFORE, THERE ARE NO
* MORE DATA SECTOR PAIRS DESCRIBED
* IN THIS T/S LIST.
LDA OPCODEFM ;CHECK TO SEE IF WRITING OR NOT.
CMP #4 ;OPCODE FOR WRITE.
BEQ NEWPAIR ;BRANCH IF WRITING.
SEC ;NOT WRITING & RAN OUT OF DATA
RTS ;SECTOR PAIRS DESCRIBED IN THE
* === ;PRESENT T/S LIST, SO GO XIT WITH
;CARRY SET 2 SIGNAL NO MORE DATA.
* SINCE WRITING & RAN OUT OF DATA
* PAIRS, MUST ADD A NEW DATA PAIR
* TO THE T/S LIST.
NEWPAIR JSR NWDATKSC ;ADD NEW DATA SEC PR TO T/S LIST,
;ZERO OUT DATA SEC BUF & SET
;UPDATE FLAG TO SIGNAL THAT BOTH
;T/S LIST SEC & DATA SEC REQUIRE
;UPDATING.
JMP SETPREV ;NOTE: IF YOU FOLLOW THIS JUMP
* --- ;THRU, YOU MAY REALIZE THAT SOME-
;TIMES WE EVENTUALLY EXIT THE
;PRESENT FUNCTION WITHOUT WRITING
;THE T/S LIST AND DATA SEC BUFS
;BACK TO THE DISK. HOWEVER, AFTER
;THE SUBFUNCTIONS ARE EXITED, THE
;CLOSE FUNCTION EVENTUALLY TESTS
;THE STATUS OF THE UPDATE FLAG
;(UPDATFLG, $B5D5) & THEN WRITES
;THE T/S LIST & DAT SEC BUFS BACK
;TO THE DISK.
* DATA SECTOR PAIR ASSOCIATED WITH
* THE DATA SECTOR WANTED WAS
* CONTAINED IN THE CURRENT T/S LIST,
* SO NOW READ IN THE DATA SECTOR.
RDDATSEC STA CURDATRK ;SAVE TRK/SEC VALS OF CURRENT DATA
INY ;SECTOR IN THE WORK AREA.
LDA (A4L),Y ;SEC# OF CURRENT DATA SEC.
STA CURDATSC
JSR READDATA ;GO READ IN THE DATA SECTOR.
* SAVE SECTOR OFFSET INTO FILE
* ASSOC WITH DATA SEC JUST READ.
SETPREV LDA FILPTSEC ;CURRENT SEC OFFSET INTO FILE.
STA RELPREV ;OFFSET IN FILE OF LAST DAT READ.
LDA FILPTSEC+1
STA RELPREV+1
* EXIT READ NEXT DATA SECTOR ROUTINE.
XITNXDAT JSR SELDABUF ;POINT A4L/H AT DATA SEC BUF.
LDY FILPTBYT ;(Y)=BYT OFFSET IN2 CUR DATA SEC.
CLC ;EXIT CLEANLY.
RTS
*=================================
* DESIGNATE TRK/SEC VALS FOR NEW
* DATA SECTOR & ADD THE NEW DATA
* SECTOR PAIR TO THE T/S LIST.
*=================================
NWDATKSC STY SCRNSRCH ;SAVE OFFSET 2 DAT PR IN T/S LST.
JSR ASGNTKSC ;FIND & DESIGNATE AN AVAIL SEC.
LDY SCRNSRCH ;RETRIEVE OFFSET TO DATA PAIR.
INY
STA (A4L),Y ;PUT NEW SEC# IN THE T/S LIST AND
STA CURDATSC ;WORK AREA.
DEY
LDA ASIGNTRK ;PUT TRK# IN T/S LST & WORK AREA.
STA (A4L),Y
STA CURDATRK
JSR SELDABUF ;POINT A4L/H AT DATA SEC BUF.
ZOUTDAT JSR ZCURBUF ;ZERO OUT DATA SEC BUF.
LDA #%11000000 ;SET BOTH BITS 6 & 7 IN FLAG TO
ORA UPDATFLG ;SIGNAL THAT BOTH DATA & T/S LIST
STA UPDATFLG ;SECTORS REQUIRE UPDATING.
RTS
*=================================
* ADJUST RECORD # OR BYTE OFFSET
* INTO A GIVEN RECORD.
*=================================
* THIS ROUTINE IS USED BOTH WHEN
* READING AND WRITING. THE PATTERN
* OF EXECUTION VARIES WITH THE
* STRUCTURE OF A FILE. HOWEVER
* SOME FILES ARE TREATED AS IF
* THEY HAVE ONE TYPE OF STRUCTURE
* WHEN THEY ARE BEING READ AND
* ANOTHER TYPE OF STRUCTURE WHEN
* THEY ARE BEING WRITTEN:
* - RANDOM ACCESS TEXT FILES HAVE
* A FIXED RECORD LENGTH ASSIGNED
* BY THE USER.
* - SEQUENTIAL TEXT & APPLESOFT
* FILES HAVE A RECORD LENGTH OF
* ONE.
* - DURING A LOAD OR BLOAD, BINARY
* & APPLESOFT FILES ARE CONSIDERED
* TO BE COMPOSED OF A COLLECTION
* OF ONE-BYTE LONG RECORDS.
* - WHEN SAVING OR BSAVING HOWEVER,
* THESE FILES ARE TREATED AS IF
* THEY CONSIST OF 1 LONG RECORD.
* COPY THE RECORD NUMBER FROM THE
* WRK AREA TO THE FM PARM LIST.
INCREC LDX RECNMBWA ;CURRENT RECORD #.
STX RECNMBFM ;RECORD # IN PARAMETER LIST.
LDX RECNMBWA+1
STX RECNMBFM+1
* COPY CURRENT BYTE OFFSET INTO
* RECORD FROM THE WORK AREA TO
* THE FM PARAMETER LIST.
LDX BYTOFFWA ;GET OFFSET IN2 RECORD (WRK AREA)
LDY BYTOFFWA+1
STX BYTOFFFM ;STORE IT IN FM PARAMETER LIST.
STY BYTOFFFM+1
* INC THE BYTE OFFSET INTO RECORD.
* IF IT EQUALS THE RECORD LENGTH,
* THEN RESET THE OFFSET TO 0 AND
* KICK UP THE RECORD NUMBER.
INX
BNE BYTVSREC
INY
BYTVSREC CPY RECLENWA+1 ;FIXED VAL VIA OPEN CMD, ELSE
;L-PARM VIA SAVE OR BSAVE CMD
;(FROM WORK AREA).
KIKOFF1 BNE SETBYTOF
CPX RECLENWA
KIKOFF2 BNE SETBYTOF
LDX #0 ;OFFSET INTO RECORD WAS SAME AS
LDY #0 ;RECORD LENGTH SO PREP TO RESET
;OFFSET INTO RECORD TO ZERO.
INC RECNMBWA
NOKIKOFF BNE SETBYTOF
INC RECNMBWA+1
* ON FALL THRU OR ENTRY FROM NOKIKOFF,
* RESET THE OFFSET INTO THE RECORD
* TO ZERO. ON BRANCHED ENTRY FROM
* KIKOFF1 OR KIKOFF2, INCREMENT THE
* OFFSET INTO THE RECORD.
SETBYTOF STX BYTOFFWA
STY BYTOFFWA+1
RTS
*=================================
* INCREMENT THE BYTE OFFSET INTO
* THE CURRENT SECTOR. IF AT THE
* END OF THE SECTOR, INCREMENT THE
* OFFSET INTO THE ENTIRE FILE
* INSTEAD.
*=================================
INCFILPT INC FILPTBYT ;KICK UP OFFSET INTO THE SECTOR.
BNE INCPTRTN ;NOT AT END OF CURRENT SECTOR.
INC FILPTSEC ;OFFSET INTO SEC WRAPPED AROUND,
BNE INCPTRTN ;SO AT END OF SEC, SO KICK UP THE
;OFFSET INTO THE ENTIRE FILE.
INC FILPTSEC+1 ;INC HI BYTE IF NECESSARY.
INCPTRTN RTS
*=================================
* POINT A4L/H AT CUR DEST'N/SOURCE
* MEMORY LOCATION (CURIOBUF) FOR
* READING/WRITING.
* INC DEST'N/SOURCE ADR FOR NEXT
* TIME AROUND.
*=================================
INCIOBUF LDY CURIOBUF ;GET ADR OF DEST'N/SOURCE LOC'N
LDX CURIOBUF+1 ;FROM FM PARM LIST.
STY A4L ;POINT A4L/H AT TARGET.
STX A4L+1
INC CURIOBUF ;KICK UP ADR OF DEST'N/SOURCE LOC
BNE INCIORTN
INC CURIOBUF+1
INCIORTN RTS
*=================================
* REDUCE COUNT OF THE # OF BYTES
* LEFT TO READ OR WRITE. WHEN THE
* COUNTER = 0, EXIT FILE MANAGER.
*=================================
DECRWLEN LDY LEN2RDWR ;LENGTH TO READ OR LENGTH-1 TO
;WRITE (FROM FM PARM LIST).
BNE DECLENRW ;MORE BYTES TO READ OR WRITE.
LDX LEN2RDWR+1 ;LOW BYTE WAS 0, CHK HI BYTE.
BEQ RWLEN0 ;COUNTER = 0 SO DONE READ/WRITE.
DEC LEN2RDWR+1
DECLENRW DEC LEN2RDWR ;REDUCE COUNTER.
RTS
RWLEN0 JMP GOODFMXT ;DONE READ/WRITE, EXIT FM.
*=========================================
* LOCATE OR CREATE A FILE ENTRY IN THE
* DIRECTORY BUFFER.
* MAKE TWO SEARCHES IF NECESSARY:
* - SEARCH1 - TRY TO LOCATE ENTRY WITH THE
* SAME NAME AS THE FILE WANTED.
* - SEARCH2 - COULDN'T LOCATE ENTRY
* CORRESPONDING TO THE FILE
* WANTED SO CREATE A NEW ENTRY
* IN THE 1RST AVAILABLE SPACE
* IN THE DIRECTORY SECTOR IN
* CASE THE CMD CAN CREATE A
* NEW FILE.
*=========================================
GETFNTRY JSR READVTOC ;READ IN VTOC SO CAN GET LINK TO
;TRKMAPS & LINK TO 1RST DIR SEC.
* PT A4L/H AT PRIMARY NAME BUF.
LDA FNAMBUFM ;GET ADR OF NAME BUF FROM THE
STA A4L ;FM PARM LIST & PUT IT IN A4L/H.
LDA FNAMBUFM+1
STA A4L+1
* TRY TO FIND THE DIRECTORY SECTOR
* CONTAINING THE NAME OF THE WANTED
* FILE. MAKE TWO SEARCHES IF NECESSARY.
* ON THE FIRST SEARCH, TRY TO FIND THE
* WANTED FILE NAME. IF THAT DOESN'T
* WORK, DO A 2ND SEARCH TO LOCATE THE
* 1RST AVAILABLE SPACE IN A DIRECTORY
* SECTOR WHERE WE CAN STORE A NEW FILE
* DESCRIPTION IN CASE THE CMD CAN CREATE
* A NEW FILE.
LDA #1 ;INIT SRCH COUNTER (SCRNSRCH), IN
SETSRCH STA SCRNSRCH ;FM SCRATCH SPACE FOR 2 SEARCHES
;(1 = SEARCH1, 0 = SEARCH2).
LDA #0 ;INIT OFFSET OF FILE DESCRIP FROM
STA SECNXD1R ;THE VERY 1RST DIRECTORY SEC.
CLC ;(C)=0=SIGNAL TO RD 1RST DIR SEC.
GETDIRSC INC SECNXD1R ;KICK UP OFFSET FROM 1RST DIR.
;(ON FIRST ENTRY: $00 ---> $01.)
JSR RDDIRECT ;GO READ DIREC SEC IN2 DIREC BUF
BCS CHNGSRCH ;LNK ZEROED OUT, NO MORE DIRECT
;SECTORS, SO GO SWITCH SEARCHES.
LDX #0
CKDIRTRK STX CURDIRNX ;OFFSET OF FILE DESCRIP INTO THE
;CURRRENT DIRECTORY SECTOR.
LDA FIL1TSTK,X ;GET TRK# OF 1RST T/S LIST SEC
;FOR A PARTICULAR FILE FROM THE
;FILE DESCRIP ENTRY IN DIR SEC.
BEQ CHRSRCHA ;IF TRK#=0, NO MORE FILES IN THIS
;DIRECTORY SECTOR.
BMI CHRSRCHB ;SKIP DELETED FILE. (WHEN A FILE
;IS DELETED, #$FF IS PUT IN BYTE
;WHERE TRK# OF 1RST T/S LIST IS
;USUALLY KEPT.)
* COMPARE NAME FOUND IN THE FILE
* DESCRIPTION ENTRY PORTION OF THE
* DIRECTORY SECTOR WITH NAME WNTD.
* (ON ENTRY, A4L/H POINTS AT THE
* PRIMARY FILE NAME BUFFER.)
LDY #0 ;INIT INDEX TO NAME BUFFER.
INX ;POINT (X) AT 1RST CHAR POS'N IN
INX ;NAME FIELD OF DESCRIP ENTRY.
CMPNAMES INX
LDA (A4L),Y ;GET CHAR OF NAME WANTED FROM THE
;PRIMARY FILENAME BUFFER.
CMP FIL1TSTK,X ;CHAR OF NAME WANTED VS CHAR IN
;DESCRIPTION ENTRY OF DIREC SEC.
BNE DONTMTCH ;CHARS (IE., NAMES) DON'T MATCH.
INY
CPY #30 ;DONE ALL CHARS YET (0 TO 29)?
BNE CMPNAMES ;CHRS MTCH, BRANCH IF MORE 2 CHK.
LDX CURDIRNX ;ALL CHARS MTCHD, SO NAMES MTCHD.
CLC ;RTN WITH (X) = INDEX TO FILE
RTS ;DESCRIP IN CURRENT DIRECTORY AND
* === ;WITH (C)=0 TO SIGNAL THAT THE
;CORRECT FILE DESCRIP WAS FOUND.
* ADVANCE INDEX TO POINT AT THE NEXT
* POTENTIAL FILE DESCRIPTION ENTRY.
DONTMTCH JSR NXPLUS35 ;NAMES DIDN'T MATCH, SO ADD 35 TO
;INDEX TO POINT IT AT NEXT ENTRY.
;(CHK TO MAKE SURE DON'T INDEX
;RIGHT OFF END OF DIRECTORY SEC.)
BCC CKDIRTRK ;MORE POTENTIAL FILE DESCRIPS TO
;CHK IN THIS DIRECTORY SECTOR.
BCS GETDIRSC ;GO GET NEXT DIRECTORY SECTOR.
* ---
* IF JUST COMPLETED FIRST SEARCH,
* GO BACK TO DO SECOND SEARCH.
CHRSRCHA LDY SCRNSRCH ;(1=SEARCH1, 0=SEARCH2)
BNE SETSRCH ;GO SWITCH TO SECOND SEARCH.
* IF FIRST SEARCH, SKIP DELETED FILES.
* IF SECOND SEARCH, FALL THRU TO STORE
* THE (NEW) DESCRIPTION IN THE 1RST
* UNUSED SPACE IN THE DIRECTORY.
CHRSRCHB LDY SCRNSRCH ;(1=SEARCH1, 0=SEARCH2)
BNE DONTMTCH
* COULDN'T LOCATE THE FILE NAME IN THE
* DIRECTORY DESCRIPTION ENTRIES, SO
* BEGIN CREATING A NEW DESCRIPTION IN
* THE FIRST AVAILABLE SPACE IN A
* DIRECTORY (IN CASE CMD CAN LEGALLY
* CREATE A NEW FILE).
NWDESCRP LDY #0 ;INIT INDEX TO PRIMARY NAME BUF.
INX ;SET INDEX TO 1RST CHAR POS'N IN
INX ;THE NAME FIELD OF FILE DESCRIP
SETNWNAM INX ;ENTRY SPACE N THE DIRECTORY SEC.
LDA (A4L),Y ;COPY CHAR FROM PRIMARY NAME BUF
STA FIL1TSTK,X ;TO DIREC DESCRIP ENTRY AREA.
INY
CPY #30 ;30 CHARS IN NAME (0 TO 29).
BNE SETNWNAM ;BRANCH IF MORE CHARS TO COPY.
LDX CURDIRNX ;RTN WITH INDEX TO FILE DESCRIP
SEC ;IN CURRENT DIRECTORY SECTOR AND
RTS ;WITH (C)=1 TO SIGNAL A NEW ENTRY
;WAS JUST CREATED.
*=====================================
* 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 SECTOR.)
*=====================================
NXPLUS35 CLC ;ADD 35 TO THE INDEX. (EACH FILE
LDA CURDIRNX ;DESCRIPTION IS 35 BYTES LONG.)
ADC #35
TAX ;CHK IF MORE SPACE FOR ENTRIES IN
CPX #245 ;CURRENT DIRECTORY.
RTS ;EXIT WITH (C) CONDITIONED:
; (C)=0=MORE SPACE IN DIRECTORY.
; (C)=1=RAN OFF END OF DIRECTORY.
*====================================
* - IF FIRST SEARCH, SWITCH TO SECOND
* SEARCH.
* - IF SECOND SEARCH, LINK ZEROED OUT
* (BECAUSE THERE ISN'T ENOUGH ROOM
* ON DISK FOR A NEW ENTRY. THERE4,
* GO EXIT WITH A DISK-FULL-ERROR
* MESSAGE.
*====================================
CHNGSRCH LDA #0 ;SET (A) = 0 SO WE CAN RESET
;SCRNSRCH IF WE HAVE 2 GO BACK 2
;DO A SECOND SEARCH.
LDY SCRNSRCH ;(1=SEARCH1, 0=SEARCH2.)
BNE SETSRCH ;JUST DID FIRST SEARCH, SO NOW GO
;BACK TO START SECOND SEARCH.
JMP DISKFULL ;EVEN THE SECOND SEARCH WAS
;UNSUCCESSFUL, SO GO HANDLE A
;DISK-FULL ERROR.
*========================================
* ASSIGN TRK(S)/SEC(S) FOR THE NEW FILE.
*========================================
* NOTE: THIS ROUTINE USUALLY ASSIGNS
* MORE SECTORS THAN ARE NEEDED. EACH
* TIME A TRK WITH ONE OR MORE FREE SECS
* IS LOCATED, THE ENTIRE TRACK IS
* IS ASSIGNED. THE UNNEEDED SECS ARE
* LATER RELEASED BY THE CLOSE COMMAND.
*
* NOTE: DOS DOES NOT SUPPORT THE
* ALLOCATION OF TRK 0 FOR A FILE.
* INSTEAD, TRK 0 IS RESERVED FOR STORING
* PART OF THE DOS IMAGE. HOWEVER, AS
* SHOWN BELOW, TRK 0 HAS SPECIAL
* SIGNIFICANCE FOR THE FOLLOWING FLAGS:
* ASIGNTRK = TRK# BEING ASSIGNED OR, IF
* ASIGNTRK=0, THEN IT IS A
* SIGNAL TO GET NEXT TRK TO
* ASSIGN FROM THE VTOC.
* TRK0YET = 0 = HAVEN'T ENCOUNTERED TRK0
* YET.
* = 1 = TRK0 HAS BEEN ENCOUNTERED.
* (TRK 0 IS USED AS A REFERENCE POINT.
* THE FIRST TIME TRK0 IS ENCOUNTERED,
* TRK0YET IS SET TO 1. THE NEXT TIME
* TRK0 IS ENCOUNTERED, THE ENTIRE DISK
* HAS BEEN SEARCHED.)
* HAS A TRK ALREADY BEEN ASSIGNED FOR
* THIS FILE?
ASGNTKSC LDA ASIGNTRK
BEQ PRPNWTRK ;BRANCH IF NO TRK ASSIGNED YET.
;(ALWAYS TAKEN 1RST TIME "JSR" TO
;HERE FRM CREATNEW. HOWEVER, WHEN
;WE LATER JSR TO HERE, ASIGNTRK
;EQUALS THE TRK # FOR T/S LIST.)
* A TRK WAS ALREADY ASSIGNED, SO NOW SEE
* IF THERE ARE ANY FREE SECS WHICH WE
* CAN USE ON THIS TRK.
ANYAVAIL DEC ASIGNSEC ;NEXT SECTOR BE ASSIGNED.
BMI ASGNWTRK ;IF DEC FROM $00 ==> #$FF, THEN
;NO MORE FREE SECS ON THIS TRK.
* CHECK IF ANY SECS ARE FREE.
CLC ;ROLL BITS IN THE 4-BYTES OF
LDX #4 ;ASIGNMAP AS AS UNIT - ROLL THEM
;BACK TO STANDARD POSITION.
ADJSTMAP ROL ASIGNMAP-1,X ;IF C=1, SEC ASSOC WITH ROLLED
DEX ;BIT POS'N IS FREE TO BE ASSIGNED
BNE ADJSTMAP ;TO A NEW FILE.
BCC ANYAVAIL ;SEC NOT FREE - GO GET NEXT ONE.
* FOUND A FREE SECTOR.
INC FILENSEC ;SEC WAS FREE, SO KICK FILE SIZE
BNE XWITHFRE ;UP BY 1 & RTN WITH FREE SEC# IN
INC FILENSEC+1 ;(A) SO IT CAN LATER BE USED FOR
XWITHFRE LDA ASIGNSEC ;THE T/S LIST SECTOR.
RTS ;(ACTUALLY ONLY GOOD EXIT AVAIL.)
* ===
* PREPARE TO ASSIGN A NEW TRK (CAUSE
* ALL SECS WERE ASSIGNED ON THE LAST TRK.)
ASGNWTRK LDA #0 ;SET SIGNAL TO ASSIGN NEW TRK.
STA ASIGNTRK
* CONTINUE PREPS TO ASSIGN NEW TRK
* OR BEGIN PREPARATIONS TO ASSIGN
* THE FIRST TRK.
PRPNWTRK LDA #0
STA TRK0YET ;SIGNAL NOT ALL TRKS CHECKED YET.
JSR READVTOC ;READ IN THE VTOC TO FIND NEXT
;TRK TO USE.
* FIND & REASSIGN FREE SECS FOR THE
* NEXT TRK. CALC NEXT TRK TO ASIGN.
GETNWTRK CLC
LDA NXTRKUSE ;GET NEXT TRK# TO ASSIGN.
ADC DRECTION ;DIRECTION (+1/-1) OF ASSIGNMENT.
BEQ CKIFFULL ;IF 0, GO SEE IF CHKD ALL TRKS.
* IS THE TRACK NUMBER LEGAL?
CMP TKPERDSK ;# OF TRKS ON DISK (FROM VTOC).
BCC CHK4FREE ;BRANCH IF TRK # IS VALID.
* TRK# TOO LARGE, SO REVERSE DIRECT'N.
LDA #$FF ;(A) = -1.
BNE SRCH4TRK ;ALWAYS.
* AT TRK0, SEE IF CHKD ALL TRKS.
* IF AT TRK0 FOR 1RST TIME, SET
* FLAG. IF 2ND TIME AT TRK0, GO
* ISSUE DISK-FULL-ERROR MESSAGE
* (BECAUSE WE SEARCHED ALL TRKS &
* DIDN'T FIND ANY FREE SECTORS).
CKIFFULL LDA TRK0YET
BNE TODSKFUL ;2ND TIME = DISK FULL.
* START THE SECOND SEARCH.
LDA #1 ;SET FLAG TO INDICATE THAT THE
STA TRK0YET ;PENDING SEARCH WILL BE 2ND ONE.
* START SEARCH AT CATALOG
* TRK PLUS OR MINUS ONE.
SRCH4TRK STA DRECTION ;SET THE SEARCH DIRECTION.
CLC ;BEGIN THE SEARCH ONE TRACK AWAY
ADC #$11 ;FROM THE CATALOG TRK.
* CHECK TRK'S TRKMAP FOR FREE SECS.
CHK4FREE STA NXTRKUSE
STA ASIGNTRK
TAY ;IRRELEVANT.
ASL ;TRK*4 CAUSE 4BYTES/TRK N TRKMAP.
ASL
TAY ;INDEX FROM LAST BYTE OF TRKMAP0.
LDX #4 ;INDEX TO THE ASIGNMAP.
CLC ;(C)=0, ASSUME NO FREE SEC AVAIL.
CPYTKMAP LDA TRKMAP0+3,Y ;COPY BYTE FROM TRKMAP TO THE
STA ASIGNMAP-1,X ;ASSIGNMENT MAP.
BEQ NXMAPBYT ;0 = SEC USED.
* FOUND A FREE SECTOR.
SEC ;(C) = 1 = FREE SECTOR FOUND.
LDA #0 ;PUT 0 IN TRKMAP 2 REASSIGN ALL 8
STA TRKMAP0+3,Y;SECS REPRESENTED BY THIS BYTE.
;(REMEMBER ONLY 2 BYTES OF TRKMAP
;ACTUALLY REPRESENT SECS. THE
;OTHER 2 BYTES ARE DUDS.)
NXMAPBYT DEY ;REDUCE INDICES TO MAPS.
DEX
BNE CPYTKMAP ;NOT DONE TRANSFERRING ALL BYTES
;FROM TRKMAP TO ASIGNMAP YET.
* CHECK IF FOUND A FREE SECTOR.
BCC GETNWTRK ;IF (C)=0,THEN NO FREE SECS FOUND
;YET SO GO BACK TO GET A NEW TRK.
JSR WRITVTOC ;UPDATE THE VTOC ON THE DISK.
LDA SECPERTK ;RESET ASIGNSEC WITH # SECS/TRK.
STA ASIGNSEC (IE 1 GREATER THAN HIGHEST SEC#.)
BNE ANYAVAIL ;ALWAYS.
*=================================
* GO ISSUE DISK-FULL-ERROR MSG.
*=================================
TODSKFUL JMP DISKFULL ;GO HANDLE ERROR.
I

View File

@@ -0,0 +1,850 @@
*=====================================
* 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 & FREE UP THE
* UNNEEDED SECTORS.
FIXMAP LDA ASIGNTRK ;HAS A TRK ALREADY BEEN ASSIGNED?
BNE FREEXTRA ;YES - GO FREE UP EXTRA SECS.
RTS ;NO - GO EXIT.
FREEXTRA PHA ;SAVE TRK # ON STK.
JSR READVTOC ;READ IN THE VTOC.
LDY ASIGNSEC ;SET (Y) = # OF NEXT SECTOR WHICH
;COULD HAVE BEEN WRITTEN.
PLA ;GET ASSIGNMENT TRK# BAK FRM STK.
CLC ;DON'T WANT 2 FREE LAST SEC USED,
;SO CLR (C) HERE SO DON'T FREE IT
;UP WHEN BEGIN ROTATING MAPS IN
;SUB2FREE ROUTINE.
JSR SUB2FREE ;ADJUST ASIGNMAP TO FREE UP SECS
;BY SETTING BIT CORRESPONDING TO
;THE SEC #. NEXT, MERGE ASIGNMAP
;WITH THE APPROPRIATE TRK MAP IN
;THE VTOC.
LDA #0 ;NO MORE DEALLOCATIONS NEEDED.
STA ASIGNTRK
JMP WRITVTOC ;WRITE CORRECTED VTOC BACK 2 DSK.
*================================
* SUBROUTINE TO FREE UP SECS 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 UNNECESSARILY
* ASSIGNED SECTORS.
* 2) IF THE DISK WAS JUST WRITTEN
* TO, ASIGNMAP MAP DOES NOT HOUSE
* ANY NEWLY ASSIGNED SECS (EVEN
* IF THOSE SECS ARE NECESSARY OR
* NOT).
* 3) SECS ARE NORMALLY ASSIGNED
* IN DESCENDING ORDER.
* 4) # OF ROR'S = # OF SECS THAT
* NEED TO BE ASSIGNED.
*
* FOR EX: IF LAST TRK HAD NEVER
* BEEN ASSIGNED & ONLY SECS $0F
* AND $0E WERE NEEDED, THEN ON
* ENTRY TO SUB2FREE, THE 1RST 2
* BYTES WOULD APPEAR AS FOLLOWS:
* SEC NMB: CBA98765 43210FED
* BIT VAL: 11111111 11111...
* AFTER THE 1RST ROR, THE STATUS
* OF SEC $0D IS DETERMINED BY THE
* ENTRY STATUS OF THE CARRY (C):
* SEC NMB: DCBA9876 543210FE
* BIT VAL: C1111111 111111..
* ON NEXT ROR, THE "CPY SECPERTK"
* INSTRUC CONDITIONS (C) TO CLR
* FOR SEC $0E:
* SEC NMB: EDCBA987 6543210F
* BIT VAL: 0C111111 1111111.
* ON NEXT ROR, THE "CPY SECPERTK"
* INSTRUC CONDITIONS (C) TO CLR
* FOR SEC $0F:
* SEC NMB: FEDCBA98 76543210
* BIT VAL: 00C11111 11111111
* WHEN ASIGNMAP IS MERGED WITH THE
* CORRESPONDING TRKMAP IN THE VTOC,
* THE SECS THAT WERE UNNECESSARILY
* ASSIGNED IN THE VTOC ARE FREED.
* (NOTE: WHEN USED IN THE DELETE
* FUNCTION, SUB2FREE IS REPEATEDLY
* CALLED BY FREESEC TO FREE ONE
* SECTOR AT A TIME.)
SUB2FREE LDX #$FC ;SET INDEX TO SHIFT 4 BYTES AS A
;UNIT (#$FC --> #$FF).
STNDARD ROR ASIGNMAP-$FC,X ;4 BYTES PER MAP FOR @ TRK.
INX
BNE STNDARD
INY ;WHEN (Y) = 16, ASIGNMAP IS BACK
;IN STANDARD POS'N.
CPY SECPERTK ;CONDITION (C) FOR NEXT SHIFT.
BNE SUB2FREE
ASL ;TRK*4 TO INDEX TRKMAP.
ASL
TAY
BEQ SUB2RTN ;TRK VAL OF 0 NOT ALLOWED.
* ASIGNMAP NOW REFLECTS TRUE SEC
* ASSIGNMENT & IS IN STANDARD
* POSITION. THERE4, MERGE IT
* WITH THE APPROPRIATE TRKMAP IN
* THE VTOC TO FREE UP EXTRA SECS.
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
*==========================================
* CALCULATE THE EXACT POSITION OF THE
* 3-BYTE FILE POINTER:
*==========================================
* - FILPTSEC = SECTOR OFFSET (IN LOW/HI
* FORMAT) INTO THE ENTIRE FILE (2 BYTES).
* - FILPTBYT = BYTE OFFSET INTO THE CURRENT
* SECTOR (1 BYTE).
*
* ALL 3 BYTES BYTES DEFINE THE EXACT POS'N
* OF THE FILE POINTER VIA THE FOLLOWING
* FORMULA:
* (REC# * REC LENGTH) + BYTE OFFSET
* INTO THE RECORD.
* WHERE:
* RECNMBFM=RECORD# 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 & ASSIGNED WITH
* THE OPEN CMD (ELSE DEFAULTED
* TO A SIZE OF 1).
* BYTOFFFM=OFFSET INTO THE CURRENT RECORD
* (SET BY USER WHEN USING THE
* OPEN CMD OR OCCASIONALLY 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- AND R-PARAMETERS
* HOWEVER YOU WANT.
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 HI ORDER BYTE OF SEC
STA FILPTSEC+1 ;OFFSET INTO THE ENTIRE FILE.
* CALCULATE: REC # * REC LENGTH.
* THIS ROUTINE IS JUST A BASIC
* MULTPLICATION OF TWO 16-BIT
* NUMBERS. IT MAY AT FIRST SEEM
* CONFUSING BECAUSE FILPTSEC &
* FILPTBYT ARE USED BOTH FOR HOLDING
* THE MULTIPLIER (RECORD #) AND PART
* OF THE PRODUCT RESULT. HOWEVER,
* THE BITS OF THE PRODUCTS 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).
LDY #16 ;16 BITS / ONE 2-BYTE NUMBER.
NMBXLEN TAX ;SAVE PART OF RUNNING PRODUCT.
;(ON 1RST ENTRY, SET (X) = 0.)
LDA FILPTBYT ;GET (A) = MULTIPLIER.
LSR ;PUT MULTIPLIER BIT IN CARRY.
BCS NMBXLEN1 ;IF (C)=1, GO ADD MULTIPLICAND.
TXA ;(A) = PART OF RUNNING PRODUCT.
BCC NMBXLEN2 ;ALWAYS, NO USE +ING MULTIPLICAND
;CAUSE BIT IN MULTIPLIER IS A 0
;SO JUST GO SHIFT RUNNING PRODUCT
NMBXLEN1 CLC ;+ MULTIPLICAND 2 RUNNING VERSION
LDA FILPTSEC+1 ;OF SHIFTED PRODUCT.
ADC RECLENWA
STA FILPTSEC+1
TXA ;SET (A)=LOW BYT OF RUNNING PROD.
ADC RECLENWA+1
NMBXLEN2 ROR ;SHIFT (AS A UNIT) RUNNING RESULT
ROR FILPTSEC+1 ;1 BIT RIGHT 4 NEXT TIME AROUND.
ROR FILPTSEC ;SHIFT LOWER 2 BYTES OF RUNNING
ROR FILPTBYT ;PRODUCT & AT SAME TIME THROW OUT
;LAST-USED MULTIPLIER BIT.
DEY ;REDUCE BIT COUNTER.
BNE NMBXLEN ;TAKE IF NOT USED ALL 16 BITS YET
* COPY BYTE OFFSET INTO RECORD FROM
* THE FM PARAMETER LIST TO THE WORK
* AREA.
CLC
LDA BYTOFFFM
STA BYTOFFWA
* CALCULATE THE LOWEST ORDER BYTE OF
* THE FILE POINTER:
* BYTOFFWA = OFFSET INTO CURRENT RECORD.
* = BYTE OFFSET INTO RECORD
* + (RECORD LENGTH * RECORD #).
ADC FILPTBYT
STA FILPTBYT
LDA BYTOFFFM+1
STA BYTOFFWA+1
ADC FILPTSEC
STA FILPTSEC
BCC CALCRTS
INC FILPTSEC+1
CALCRTS RTS
* RESIDUAL JUNK
HEX B5 ;GARBAGE LEFT OVER FRM OLD ROUT'N
RTS ;PRIOR TO PATCH TO CALCFPTR.
;CONSIDER AS FREE SPACE.
*=================================
* EXIT FM WITH OR WITHOUT ERRS.
*=================================
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 TO SIGNAL GOOD OPERATION.
BCC FMEXIT
BADFMXIT SEC ;(C) = 1 TO SIGNAL UNSUCCESSFUL.
* COMMON FM EXIT ROUTINE.
* NOTE THAT ROUTINE IS EXITED BY
* RESETTING THE STACK POINTER.
* USUALLY RETURNS TO CALLER OF THE
* FUNCTION (IE. NORMALLY RETURNS TO
* AFTRFUNC, $A6AB) IN THE FMDRIVER
* ROUTINE ($A6A8).) HOWEVER, THERE
* IS ONE EXCEPTION. THE APPEND CMD
* HNDLR (CMDAPPND, $A298) MAY CALL
* THIS ROUTINE SEVERAL TIMES. MOST
* OF THE TIME, EXECUTION RTNS TO
* AFTRFUNC. HOWEVER, THE LAST TIME
* FMEXIT IS CALLED, THE CONTENTS OF
* STKSAV ($B39B) ARE ALTERED BEFORE
* FMEXIT IS ENTERED. THIS FORCES
* AN EXIT TO CALLER OF APPEND CMD
* HNDLR (RATHER THAN TO CALLER OF
* FUNCTION HNDLR). IN THIS LATER
* INSTANCE, EXECUTION ACTUALLY RTNS
* TO AFTRCMD ($A17D) LOCATED IN THE
* COMMAND PARSING & PROCESSING ROUTINES.
FMEXIT PHP
STA RTNCODFM ;STORE RTN CODE IN FM PARM LIST.
LDA #0 ;AVOID THAT INFAMOUS $48 BUG.
STA STATUS
JSR CPYFMWA ;COPY WORK AREA TO WORK BUFFER.
PLP ;RETRIEVE STATUS OF SUCCESS OF
;OPERATION BACK OFF STK.
LDX STKSAV ;ADJUST STK POINTER TO FORCE EXIT
TXS ;TO CALLER EVEN IF SEVERAL
RTS ;SUBRT'NS DEEPER THAN ORIG ENTRY.
*=================================
* FILE MANAGER SCRATCH SPACE.
* ($B397 - $B3A3)
*=================================
CURDIRTK DS 1 ;TRK# OF CURRENT DIRECTORY SEC.
CURDIRSC DS 1 ;SEC# OF CURRENT DIRECTORY SEC.
WABUFADR HEX 0000 ;UNUSED ($B399-$B39A).
STKSAV DS 1 ;SECOND STACK POINTER SAVE AREA.
;USED TO RESET THE STACK TO FORCE
;EXECUTION TO RTN TO A DESIRED
;ROUTINE. (NORMALLY RETURNS TO
;AFTRFUNC ($A6AB) AFTR @ FUNCTION
;IS CALLED. HOWEVER, ALSO USED BY
;THE APPEND CMD 2 FORCE EXECUTION
;TO RTN TO AFTRCMD ($A17D).)
;P.S. DON'T CONFUSE STKSAV WITH
;THE 1RST STACK POINTER SAVE AREA
;(STKSAVED, $AA59).
CURDIRNX DS 1 ;BYTE OFFSET OF FILE DESCRIPTION
;ENTRY INTO CURRENT DIREC SEC.
SCRNSRCH DS 1 ;- CATALOG SCRN LINE COUNTER.
;- DESCENDING CNTR 4 # OF SRCHS
; DONE 2 LOCATE A MATCHING NAME
; OR EMPTY SPACE FOR A NEW FILE
; DESCRIP ENTRY IN DIRECTORY SEC
; (SEARCH1 = 1, SEARCH2 = 0).
;- OFFSET OF DAT PR FROM START OF
; A GIVEN T/S LIST.
TRK0YET DS 2 ;ASSIGNMENT FLAG = SIGNAL IF TRK0
;ENCOUNTERED YET (ONLY 1RST BYTE
;USED):
; $00=TRK0 NOT ENCOUNTERED YET.
; $01 = TRK0 ENCOUNTERED.
;(USED TO SEE IF ENTIRE DISK HAS
;BEEN SCANNED WHEN LOOKING 4 FREE
;SECS TO ASSIGN.)
LOKUNMSK = TRK0YET ;LOCK/UNLOCK MASK ($80/$00).
FRETKMSK HEX 0000FFFF ;4-BYTE MASK USED BY INIT FUNC'N
;TO FREE AN ENTIRE TRACK.
*=================================
* CONVERSION TABLE FOR PRVOLNMB.
* ($B3A4 - $B3A6)
*=================================
BASETEN HEX 010A64 ;10^0=0, 10^1=10, 10^2=100.
*=================================
* CHARACTER CODE FILE TYPE SYMBOLS
* USED BY THE CATALOG ROUTINE.
* ($B3A7 - $B3AE)
*=================================
FTYPETBL ASC "TIABSRAB" ;TEXT, INTEGER, APPLESOFT, BINARY
;S-TYPE, R(ELOCATABLE)-TYPE,
;A-TYPE, B-TYPE. THESE CODES ARE
;FREQUENTLY CHANGED BY HACKERS.)
*=================================
* DISK VOLUME SPELLED BACKWARDS.
* ($B3AF - $B3BA)
*=================================
DSKVOLUM ASC " EMULOV KSID" ;THESE CHRS ARE OFTEN CHANGED
;TO PERSONALIZE A CATALOG.
*=================================
* VOLUME TABLE OF CONTENTS (VTOC)
* BUFFER ($B3BB - $B4BA).
*=================================
VTOCBUFF DS 1 ;UNUSED ($B3BB).
;REFERENCE FOR START OF TABLE.
FIRDIRTK DS 1 ;TRK# OF 1RST DIRECTORY SECTOR.
FIRDIRSC DS 1 ;SEC# OF 1RST DIRECTORY SECTOR.
VERSION HEX 03 ;DOS VERSION RELEASE NUMBER.
DS 2 ;UNUSED ($B3BF-$B3C0).
VOLUSED DS 1 ;DISK VOL# (NORMALLY, $FE).
DS 32 ;UNUSED ($B3C2-$B3E1).
MXIN1TSL HEX 7A ;MAX # OF SECS THAT CAN BE LISTED
;IN A T/S LIST SEC ($7A, #122).
DS 8 ;UNUSED ($B3E3-$B3EA).
NXTRKUSE DS 1 ;NEXT TRACK TO ASSIGN.
DRECTION DS 1 ;TRK ASGNMENT DIRECT'N (+1 OR -1)
DS 2 ;UNUSED ($B3ED-$B3EE).
TKPERDSK HEX 23 ;TRKS/DISK (#35).
;AFTER DRIVE ADJUSTMENT, VALUE IN
;TKPERDSK CAN BE ALTERED 2 ENABLE
;THE USE OF AN EXTRA TRK ON DISK.
SECPERTK HEX 10 ;SECS/TRK ($10, #16, $00 --> $0F)
BYTPERSC HEX 0001 ;BYTES/SECTOR ($0100, #256).
*------------------------------------
* TRACK/SECTOR MAPS IN VTOC.
* ($B3F3 - $B47E)
*------------------------------------
* MAPS OF SECTOR USAGE ON EACH TRK.
* EACH TRK IS REPRESENTED BY FOUR
* BYTES. THE BITS IN THESE BYTES
* DEFINE THE SECTOR USAGE BY THE
* FOLLOWING CONVENTION:
* SET BIT = FREE SECTOR.
* CLEAR BIT = USED SECTOR.
* 1RST BYTE: FEDC BA98
* 2ND BYTE: 7654 3210
* (THE 3RD & 4TH BYTES ASSOCIATED
* WITH @ TRK ARE WASTED. THESE BYTES
* ARE WASTED BECAUSE THEY ARE WRITTEN
* OVER BY DOS BUT NOT ACTUALLY USED
* FOR ANYTHING. THERE4 THEY ARE NOT
* READILY AVAILABLE TO THE ASSEMBLY
* LANGUAGE PROGRAMMER THAT IS IN
* DESPERATE NEED OF AN AVAIABLE HOLE
* IN DOS.)
TRKMAP0 HEX 00000000 ;$B3F3: TRK0 (DOS IMAGE).
TRKMAP1 HEX 00000000 ;$B3F7: TRK1 (DOS IMAGE).
TRKMAP2 HEX 00000000 ;$B3FB: TRK2 (SECS 0 TO 4 USD FOR
;DOS IMAGE. REST OF SECS ARE
;SET ASIDE BUT NOT USED BY DOS.
;THEY ARE FREE TO THE USER AFTER
;ALTERING TRKMAP2, USING RWTS
;DIRECTLY OR ALTERING THE BOOT.)
TRKMAP3 DS 4 ;$B3FF: TRK 3
TRKMAP4 DS 4 ;$B403: TRK4
TRKMAP5 DS 4 ;$B407: TRK5
TRKMAP6 DS 4 ;$B40B: TRK6
TRKMAP7 DS 4 ;$B40F: TRK7
TRKMAP8 DS 4 ;$B413: TRK8
TRKMAP9 DS 4 ;$B417: TRK9
TRKMAP10 DS 4 ;$B41B: TRK$0A
TRKMAP11 DS 4 ;$B41F: TRK$0B
TRKMAP12 DS 4 ;$B423: TRK$0C
TRKMAP13 DS 4 ;$B427: TRL$0D
TRKMAP14 DS 4 ;$B42B: TRK$0E
TRKMAP15 DS 4 ;$B42F: TRK$0F
TRKMAP16 DS 4 ;$B433: TRK $10
TRKMAP17 DS 4 ;$B437: TRK$11 (DIRECT/VTOC).
TRKMAP18 DS 4 ;$B43B: TRK$12
TRKMAP19 DS 4 ;$B43F: TRK$13
TRKMAP20 DS 4 ;$B443: TRK$14
TRKMAP21 DS 4 ;$B447: TRK$15
TRKMAP22 DS 4 ;$B44B: TRK$16
TRKMAP23 DS 4 ;$B44F: TRK$17
TRKMAP24 DS 4 ;$B453: TRK$18
TRKMAP25 DS 4 ;$B457: TRK$19
TRKMAP26 DS 4 ;$B45B: TRK$1A
TRKMAP27 DS 4 ;$B45F: TRK$1B
TRKMAP28 DS 4 ;$B463: TRK$1C
TRKMAP29 DS 4 ;$B467: TRK$1D
TRKMAP30 DS 4 ;$B46B: TRK$1E
TRKMAP31 DS 4 ;$B46F: TRK$1F
TRKMAP32 DS 4 ;$B473: TRK$20
TRKMAP33 DS 4 ;$B477: TRK$21
TRKMAP34 HEX FFFF0000 ;$B47B: TRK$22
*---------------------------------
* UNUSED PART OF VTOC
* ($B47F - $B4BA)
*---------------------------------
DS 60 ;UNUSED ($B47F-$B4BA).
*=================================
* DIRECTORY SECTOR BUFFER.
* ($B4BB - $B5BA)
*=================================
DIRECBUF HEX 00 ;UNUSED-REFERENCE 4 START OF BUF.
DIRLNKTK DS 1 ;TRK OF NEXT DIRECTORY SECTOR.
DIRLNKSC DS 1 ;SECTOR OF NEXT DIRECTORY SECTOR.
DS 8 ;UNUSED ($B4BC-$B4C5).
*---------------------------------
* FILE DESCRIPTION ENTRIES.
* ($B4C6 - $B5BA)
*---------------------------------
FIL1TSTK DS 1 ;FILE1: T/S LIST TRK ($B4C6)
FIL1TSSC DS 1 ; T/S LIST SEC ($B4C7)
FIL1TYPE DS 1 ; FILE TYPE ($B4C8)
FIL1NAME DS 30 ; NAME ($B4C9-$B4E6)
FIL1SIZE DS 2 ; SIZE ($B4E7-$B4E8)
FIL2TSTK DS 1 ;FILE2: T/S LIST TRK ($B4E9)
FIL2TSSC DS 1 ; T/S LIST SEC ($B4EA)
FIL2TYPE DS 1 ; TYPE ($B4EB)
FIL2NAME DS 30 ; NAME ($B4EC-$B509)
FIL2SIZE DS 2 ; SIZE ($B50A-$B50B)
FIL3TSTK DS 1 ;FILE3: T/S LIST TRK ($B50C)
FIL3TSSC DS 1 ; T/S LIST SEC '$B50D)
FIL3TYPE DS 1 ; TYPE ($B50E)
FIL3NAME DS 30 ; NAME ($B50F-$B52C)
FIL3SIZE DS 2 ; SIZE ($B52D-$B52E)
FIL4TSTK DS 1 ;FILE4: T/S LIST TRK ($B52F)
FIL4TSSC DS 1 ; T/S LIST SEC ($B530)
FIL4TYPE DS 1 ; TYPE ($B531)
FIL4NAME DS 30 ; NAME ($B532-$B54F)
FIL4SIZE DS 2 ; SIZE ($B550-$B551)
FIL5TSTK DS 1 ;FILE5: T/S LIST TRK ($B552)
FIL5TSSC DS 1 ; T/S LIST SEC ($B553)
FIL5TYPE DS 1 ; TYPE ($B554)
FIL5NAME DS 30 ; NAME ($B555-$B572)
FIL5SIZE DS 2 ; SIZE ($B573-$B574)
FIL6TSTK DS 1 ;FILE6: T/S LIST TRK ($B575)
FIL6TSSC DS 1 ; T/S LIST SEC ($B576)
FIL6TYPE DS 1 ; TYPE ($B577)
FIL6NAME DS 30 ; NAME ($B578-$B595)
FIL6SIZE DS 2 ; SIZE ($B596-$B597)
FIL7TSTK DS 1 ;FILE7: T/S LIST TRK ($B598)
FIL7TSSC DS 1 ; T/S LIST SEC ($B599)
FIL7TYPE DS 1 ; TYPE ($B59A)
FIL7NAME DS 30 ; NAME ($B59B-$B5B8)
FIL7SIZE DS 2 ; SIZE ($B5B9-$B5BA)
*=================================
* FILE MANAGER PARAMETER LIST.
* ($B5BB - $B5D0)
*=================================
OPCODEFM DS 1 ;FM OPERATION CODE.
SUBCODFM DS 1 ;FM OPERATION SUBCODE.
RECNMBFM DS 2 ;FM PARM LST VERSION OF RECORD #.
;(USUALLY 1 LESS THAN RECNMBWA.)
;(SEE DESCRIPTION OF THE RECORD
;NUMBER GIVEN IN THE WORK AREA
;LISTED BELOW.)
BYTOFFFM DS 2 ;BYTE OFFSET INTO RECORD.
LEN2RDWR DS 2 ;LENGTH TO READ OR LENGTH-1
;TO WRITE. (INIT VAL & COUNTER).
;ALSO USED AS A TEMPORARY BUF TO
;TRANSFER ADDR & LENGTH BYTES TO
;ONEIOBUF BUF WHEN USING THE
;WRITE-ONE-BYTE AND READ-ONE-BYTE
;SUBFUNCTIONS.
CURIOBUF DS 2 ;ADDR OF CURRENT I/O BUFFER.
RTNCODFM DS 1 ;RETURN CODE. (CONTRARY TO WHAT
;SOME ARTICLES SUGGEST, THE VALUE
;IN THIS BYTE IS ONLY RELEVANT IF
;AN ERROR OCCURS.)
DS 1 ;UNUSED ($B5C6).
WRKBUFFM DS 2 ;PTS TO WORK BUF (IN DOS CHAIN).
TSBUFFM DS 2 ;PTS TO T/S LIST SEC BUF (CHAIN).
DATBUFFM DS 2 ;PTS TO DATA SECTOR BUF (CHAIN).
NXTNAME DS 2 ;PTS TO NEXT DOS NAME BUFFER IN
;CHAIN. (SET UP, BUT NOT USED.)
DS 2 ;UNUSED ($B5CF-$B5D0).
FMPRMLST = OPCODEFM ;START OF FM PARAMETER LIST.
FIRDOSPG = OPCODEFM ;CONTAINS 1RST PAGE# OF DOS WHEN
;WRITING DOS IMAGE DURING INIT.
RECLENFM = RECNMBFM ;FM PARM LIST VERSION OF THE
;RECORD LENGTH. (SEE DESCRIPTION
;OF RECORD LENGTH DESCRIBED IN
;THE WORK AREA LISTING BELOW.)
RENAMBUF = RECLENFM ;PTS 2 BUFFER CONTAINING NEW FILE
;NAME. (USED IN RENAME CMD.)
VOLFM = BYTOFFFM ;VOLUME# WANTED.
DRVFM = BYTOFFFM+1 ;DRIVE# WANTED.
SLOTFM = LEN2RDWR ;SLOT NUMBER.
FILTYPFM = LEN2RDWR+1 ;FILE TYPE CODE (INCLUDING THE
;LOCKED/UNLOCKED STATUS).
FNAMBUFM = CURIOBUF ;FILE NAME ADDRESS.
ONEIOBUF = CURIOBUF ;A ONE-BYTE I/O BUFFER.
*=================================
* FILE MANAGER WORK AREA.
* ($B5D1 - $B5FF)
* (DON'T CONFUSE WITH THE VARIOUS
* WORK BUFFERS CONTAINED IN THE
* CHAIN OF DOS BUFFERS.)
*=================================
FMWKAREA DS 1 ;SIMPLY USED FOR REFERENCE POINT.
FIRSTSTK = FMWKAREA ;TRK# OF 1RST T/S LIST SEC.
FIRTSSEC DS 1 ;SEC # OF 1RST T/S LIST SEC.
CURTSTRK DS 1 ;TRK# OF CURRENT T/S LIST SEC.
CURTSSEC DS 1 ;SEC# OF CURRENT T/S LIST SEC.
UPDATFLG DS 1 ;FLAG TO UPDATE DIFFERENT TYPES
;OF SECTORS:
; $02=LAST OPERATION WAS A WRITE.
; $20=VTOC NEEDS UPDATING.
; $40=DATA SEC NEEDS UPDATING.
; $80=T/S LST SEC NEEDS UPDATING.
CURDATRK DS 1 ;TRK# OF CURRENT DATA SECTOR.
CURDATSC DS 1 ;SEC# OF CURRENT DATA SECTOR.
SECNXD1R DS 1 ;OFFSET OF FILE DESCRIPTION FROM
;THE VERY FIRST DIRECTORY SEC.
BYTNXD1R DS 1 ;OFFSET OF FILE DESCRIPTION INTO
;THE CURRENT DIRECTORY SEC.
MXSCURTS DS 2 ;MAXIMUM # OF SECS THAT CAN BE
;LISTED IN A T/S LIST.
RELFIRST DS 2 ;RELATIVE SEC # (IN RELATION TO
;THE ENTIRE FILE) OF THE FIRST
;DATA SEC THAT IS (OR CAN BE)
;LISTED IN THE CURRENT T/S LIST.
;(POSSIBLE VALS ARE:$0000, $007A,
;2*$007A, 3*$007A OR 4*$007A.)
RELASTP1 DS 2 ;ONE GREATER THAN THE MAXIMUM
;RELATIVE SEC# (IN RELATION 2 THE
;ENTIRE FILE) OF THE LAST DAT SEC
;THAT CAN POSSIBLY BE DESCRIBED
;IN THE CURRENT T/S LIST.
;(POSSIBLE VALUES ARE: $007A,
;2*$007A, 3*$007A, 4*$007A AND
;5*$007A.)
RELPREV DS 2 ;RELATIVE SEC# (IN RELATION 2 THE
;ENTIRE FILE) OF THE LAST DAT SEC
;THAT WAS READ OR WRITTEN.
;(POSSIBLE VAL ARE: $0000, $007A,
;2*$007A, 3*$007A OR 4*$007A.)
SECSIZWA HEX 0001 ;BYTES/SECTOR (#256, $00-$FF).
* --- FILE POINTER ---
* (3 BYTES)
FILPTSEC DS 2 ;SECTOR OFFSET OF PTR (2 BYTES).
FILPTBYT DS 1 ;BYTE OFFSET PORTION OF POINTER.
WASTEBYT DS 1 ;WEIRD FLG USED BY THE APPEND CMD
;(VIA RSETPTRS, $B6B3) WHEN
;BACKING UP THE FILE POINTER AND
;TESTED (IN APNDPTCH, $B692)
;WHENEVER AN OUT-OF-DATA ERROR IS
;ENCOUNTERED.
RECLENWA DS 2 ;RECORD LENGTH.
RECNMBWA DS 2 ;CURRENT RECORD NUMBER.
BYTOFFWA DS 2 ;CURRENT BYTE OFFSET INTO RECORD.
;- RANDOM ACCESS TXT FILES HAVE A
; FIXED RECORD LNGTH ASSIGNED BY
; THE USER.
;- SEQUENTIAL TEXT AND APPLESOFT
; FILES HAVE A RECORD LENGTH OF
; ONE.
;- DURING A LOAD OR BLOAD, APPLE-
; SOFT OR BINARY FILES ARE
; CONSIDERED TO BE COMPOSED OF A
; COLLECTION OF ONE-BYTE LONG
; RECORDS.
;- WHEN SAVING OR BSAVING HOWEVER
; THESE FILES ARE TREATED AS IF
; THEY CONSIST OF A SINGLE VERY
; LONG RECORD.
FILENSEC DS 2 ;FILE LENGTH IN SECTORS.
ASIGNSEC DS 1 ;NEXT SECTOR TO ASSIGN.
ASIGNTRK DS 1 ;NEXT TRK TO ASSIGN.
ASIGNMAP DS 4 ;4-BYTE MAP OF SEC USAGE ON THE
;TRK BEING ASSIGNED.
FILTYPWA DS 1 ;FILE TYPE CODE (INCLUDING THE
;LOCKED OR UNLOCKED STATUS).
SLOT16WA DS 1 ;SLOT*16.
DRVWA DS 1 ;DRIVE NUMBER.
VOLWA DS 1 ;1'S COMPLEMENT OF VOLUME NUMBER.
TRKWA DS 1 ;TRACK NUMBER.
HEX 0000000000 ;UNUSED ($B5FB-$B5FF).
*=================================
* IMAGE OF BOOT1 ($B600-$B6FF)
*=================================
* - STORED ON TRK0/SEC0.
* - READ IN AT $800-$8FF BY DISK CONTROLLER ROM (BOOT0).
* - EXECUTION BEGINS AT $0801 & USES THE CONTROLLER'S READ-
* SECTOR SUBROUTINE (BTRDSEC, $CS00, WHERE S = SLOT # OF
* CARD) TO READ IN TRK0/SEC9 DOWN TO TRK0/SEC1 (THAT IS,
* $BFFF ----> $B600).
* NOTE: IN ORDER TO GENERATE AN ACCURATE SYMBOL TABLE THAT
* CAN BE APPLIED TO BOTH THE FORMATTED AND LINEAR DIS-
* ASSEMBLIES, AND BECAUSE DIFFERENT ASSEMBLERS VARY IN
* THEIR ABILITIES TO ACCEPT CERTAIN OBJECT VALUES OR RE-ORG
* DURING ASSEMBLY, THE FOLLOWING SPECIAL LABEL SYSTEM HAS
* BEEN CREATED:
* IMAGE LBL/ADR EXECUTION LBL/ADR COMMENTS
* --------------- ----------------- --------------------
* SEC2RDB6, $B600 SEC2RDB08, $800 ;DEFINES # OF SECS 2
* ;BE READ IN BY BOOT0
* BT1EXCB6, $B601 BT1EXC08, $801 ;START BT1 EXECUTION
* ;BOOT0 JMPS TO HERE.
* SKPRELB6, $B61F SKPREL08, $81F ;TARGET LBL 4 BRNCH.
* PRP4B2B6, $B639 PRP4B208, $839 ;TARGET LBL 4 BRNCH.
* IMG8FD, $B6FD BT1LDADR, $8FD ;BOOT1 LOAD ADDRESS.
* ;VARIES FROM $B600 2
* ;$BF00. EVENTUALLY
* ;PTS 2 START BOOT2
* ;($B700).
* IMG8FF, $B6FF BT1PG2RD, $8FF ;CONTAINS # OF SECS
* ;TO READ IN WHEN
* ;EXECUTING BOOT1.
* ;ALSO DOUBLES AS
* ;LOGICAL SEC #.
* ;VARIES FROM:
* ;$09 --> $00 --> $FF.
* AS INDICATED ABOVE, SEC2RD08 ($800) DEFINES # OF SECS
* TO BE READ IN BY BOOT0. THIS VALUE IS NORMALLY $01
* (MEANING READ ONLY SEC0 OF TRK0). HOWEVER, YOU CAN ZAP
* TRK0/SEC0/OFFSET0 WITH A LARGER VALUE ($01 TO $10) TO
* READ IN MORE SECS FROM TRK0. ALSO NOTE THAT MOST
* REFERENCES SAY THAT SEC2RD08 NORMALLY CONTAINS A "$00"
* (RATHER THAN A "$01"). BECAUSE THE TEST AT $CS56 USES
* THE CARRY, EITHER VAL WILL CAUSE ONLY 1 SEC 2 BE READ IN
* HOWEVER, "$01" IS THE VALUE USED BY DOS. (CONFUSION MAY
* STEM FROM THE FACT THAT APPLESOFT LATER STORES A $00 IN
* $800.)
SEC2RDB6 HEX 01 ;IMAGE OF SEC2RD08. DENOTES # OF
;SECS TO BE READ FROM TRK0 DURING
;BOOT0.
BT1EXCB6 LDA PT2BTBUF+1 ;IMAGE OF BT1EXC08. GET NEXT PAGE
;TO BE READ IN.
CMP #$09 ;IS IT PAGE 9 (IE. 1RST PAGE READ
;BY BOOT1)?
BNE SKPRELB6 ;NO - ALREADY USED BY BOOT1 TO
;READ PAGE9, SO SKIP POINTER
;INITIALIZATION GIVEN BELOW.
* INITIALIZE THE POINTER (PTR2RDSC)
* TO POINT AT BOOT0'S READ SECTOR
* SUBROUTINE (BTRDSEC, $CS5C;
* WHERE S=SLOT#, NORMALLY $C65C).
LDA SLT16ZPG ;(A) = SLOT*16 FROM ZERO PAGE.
LSR ;DIVIDE BY 16.
LSR
LSR
LSR
ORA #$C0 ;MERGE WITH $C0 TO GET $CS, WHERE
;S=SLOT#.
STA PTR2RDSC+1 ;STORE HI BYTE OF CONTROLLER'S
;READ-SECTOR SUBROUTINE ADDR.
LDA #<BTRDSEC ;GET LOW BYTE OF SUBRTN ADR.
STA PTR2RDSC ;(LOW BYTE IS A CONSTANT (#$5C) &
;IS THERE4 NOT VARIABLE WITH SLOT
;USED (AS IS HI BYTE).)
* READ IN 9 SECTORS REPRESENTED BY
* TRK0/SEC9 DOWN TO TRK0/SEC1 INTO
* $BFFF TO $B600. NOTE THAT THE
* SECS ARE READ IN FROM HIGHER TO
* LOWER MEMORY. THESE SECS CONTAIN
* THE IMAGE OF BOOT1, PART OF THE
* FILE MANAGER AND ALMOST ALL OF
* RWTS & ITS ASSOCIATED ROUTINES.
* CALCULATE THE TARGET ADDR FOR
* THE FIRST SECTOR TO BE READ IN.
CLC
LDA BT1LDADR+1 ;CONTAINS $B6 ON 48K SLAVE.
ADC BT1PG2RD ;CONTAINS #09 ON 48K SLAVE.
STA BT1LDADR+1 ;(A) = $BF ON 48K SLAVE.
* DETERMINE # OF PAGES (SECS) LEFT
* 2 READ, PHYSICAL SECTOR# & TARGET
* ADDRESS. THEN, GO READ IN THE
* NEXT SECTOR.
SKPRELB6 LDX BT1PG2RD ;IMAGE OF SKRPREL08 ($81F).
;(X)=PAGES LEFT 2 READ (MINUS 1).
;(ALSO DOUBLES AS LOGICAL SEC#.
;VARIES FROM $09-->$FF).
BMI PRP4B2B6 ;WHEN (X) = #$FF, THEN WE HAVE
;READ ALL THE SECS IN, SO GO XIT.
LDA PHYSECP8-$AE00,X ;EQUIVALENT 2 "LDA $84D,X".
;CONVERT LOGICAL SEC# 2 PHYS SEC#
STA BOOTSEC ;STORE PHYSICAL SEC# IN PAGE0.
DEC BT1PG2RD ;REDUCE PAGES (SECS) LEFT TO READ
;FOR NEXT TIME AROUND.
LDA BT1LDADR+1 ;POINT BUFFER POINTER AT TARGET
STA PT2BTBUF+1 ;ADR. (VARIES FROM $BF TO $B6
;ON 48K SLAVE).
DEC BT1LDADR+1 ;REDUCE HI BYTE OF I/O BUF FOR
;NEXT TIME AROUND. (VARIES FROM
;$BF TO $B5 ON 48K SLAVE.)
LDX SLT16ZPG ;SET (X) = SLOT*16.
JMP (PTR2RDSC) ;EQUIVALENT TO "JMP ($8FD)" OR
;"JMP $CS5C" TO GO READ IN THE
;NEXT SECTOR.
;************ NOTE **************
;* GOES TO BT1EXC08 ($801) AFTER*
;* EACH SECTOR IS READ IN. *
;* (REMEMBER, BT1EXCB6 IS A *
;* CARBON COPY OF BT1EXC08.) *
;********************************
* PREPARE FOR BOOT2.
PRP4B2B6 INC BT1LDADR+1 ;IMAGE OF PR4B208 ($839).
;POINT AT THE LOAD ADR FOR BOOT2.
INC BT1LDADR+1 ;(AFTR INCS, = $B7 ON 48K SLAVE).
* SET FULL SCREEN TEXT & DESIGNATE
* KEYBOARD & SCREEN AS I/O DEVICES.
JSR SETKBD ;SIMULATE IN#0 (SET KSW: KEYIN).
JSR SETVID ;SIMULATE PR#0 (SET CSW: COUT1).
JSR INIT ;SIMULATE A "TEXT" STATEMENT.
LDX SLT16ZPG ;(X) = SLOT*16.
* ------ GO TO BOOT2 ------ *
JMP (BT1LDADR) ;JMP 2 BOOT2 ($B700 ON 48K SLAVE)
*=================================
* TABLE OF PHYSICAL SECTOR #'S.
* ($B64D - $B65C)
* - AN IMAGE OF THIS TABLE IS
* HOUSED AT $84D DURING THE BOOT.
*=================================
;CORRESPONDING LOGICAL SECTOR #
PHYSECP8 HEX 00 ; $00
HEX 0D ; $01
HEX 0B ; $02
HEX 09 ; $03
HEX 07 ; $04
HEX 05 ; $05
HEX 03 ; $06
HEX 01 ; $07
HEX 0E ; $08
HEX 0C ; $09
HEX 0A ; $0A
HEX 08 ; $0B
HEX 06 ; $0C
HEX 04 ; $0D
HEX 02 ; $0E
HEX 0F ; $0F
E

View File

@@ -0,0 +1,508 @@
*=================================
* OTHER ERROR PATCH.
* ($B65D - $B670)
* - USED WHEN FM DRIVER GETS AN
* ERROR THAT IS NOT AN OUT-OF-
* DATA ERROR.
* - ALSO CONTAINS THE APPEND FLAG.
*=================================
APPNDFLG HEX 00 ;APPEND FLAG.
* ERROR WAS DEADLY, SO BETTER
* RELEASE THE FILE'S BUFFER AND
* MAKE SURE THE APPEND FLAG IS OFF.
OTHRERR JSR GETBUFF ;LOCATE BUFFER BELONGING TO THE
;FILE. (PUT ADR IN A3L/H PTR.)
BCS TOERRMSG ;NO BUFFER WAS ASSIGNED, SO NO
;NEED 2 RELEASE THE FILE'S BUF OR
;TURN OFF THE APPEND FLAG.
LDA #0 ;ZERO OUT THE APPEND FLAG & SET
TAY ;(Y) TO NDEX THE 1RST BYTE OF THE
STA APPNDFLG ;DOS NAME BUFFER.
STA (A3L),Y ;RELEASE FILE'S DOS BUFFER.
TOERRMSG LDA RTNCODFM ;GET ERROR CODE TO INDEX ERR MSG.
JMP ERRHNDLR ;EXIT & GO PRINT ERROR MESSAGE.
*=================================
* PATCH TO HANDLE APPEND.
* ($B671 - $B685)
*=================================
* PREPARE TO MANUALLY BACK UP THE
* FILE POINTER IF NECESSARY. NEED
* TO BACK IT UP ONE BYTE IF A $00
* BYTE WAS ENCOUNTERED IN A DATA
* SECTOR. HOWEVER, IF A ZEROED-
* OUT DATA PAIR (LISTED IN A T/S
* LIST) OR A ZEROED-OUT T/S LINK
* WAS ENCOUNTERED, THEN THE FILE
* POINTER IS POSITIONED CORRECTLY.
* (P.S. AT ONE TIME IN THE HISTORY
* OF DOS, THE POSITION FUNCTION
* WAS USED TO BACK UP THE POINTER.)
* ENTER WITH APPEND FLAG SET IF A
* $00 WAS DETECTED IN A (NON-EMPTY)
* FILE'S T/S LIST.
CKAPFLG LDA APPNDFLG ;IS APPEND FLAG ON?
BEQ CLRAPFLG ;NO - FLAG IS OFF.
INC RECNMBFM ;YES -SO INCREMENT THE FILE MGR'S
BNE CLRAPFLG ;VERSION OF THE RECORD # BECAUSE
INC RECNMBFM+1 ;RECNMBFM IS POINTING AT THE LAST
;VALID DATA BYTE AND WE WANT IT 2
;POINT AT THE NEXT POTENTIAL
;RECORD NUMBER. (P.S. REMEMBER
;THAT RECNMBFM LAGS RECNMBWA BY
;ONE BYTE.)
CLRAPFLG LDA #0 ;DON'T NEED THE APPEND FLAG ANY
STA APPNDFLG ;MORE, SO TURN IT OFF.
JMP RSETPTRS ;GO BACK UP THE FILE POINTER.
*==================================
* PATCH TO VERIFY A RANGE-OF-BYTES.
* (CALLED BY RWRANGE TO R/W RANGE
* OF BYTES & THEN VERIFY THE DATA.)
*==================================
VRFYRWNG STA SUBCODFM ;PUT RANGE-OF-BYTES SUBCODE IN
;RWTS'S IOB.
JSR FMDRIVER ;CALL FM DRIVER TO READ/WRITE A
;RANGE OF BYTES.
JSR CMDCLOSE ;CLOSE FILE & THEN VERIFY DATA.
JMP CMDVERFY
*================================
* APPEND PATCH.
* ($B692 -$B6B2)
* - USED TO HANDLE AN END-OF-DATA
* ERROR.
*================================
* THIS PATCH IS DIFFICULT TO UNDER-
* STAND BECAUSE IT IS A PATCH THAT
* HAS BEEN ADDED TO REPAIR PREVIOUS
* PATCHES AND BECAUSE EXECUTION FAILS
* ON OCCASSION. AS A RESULT, THE APPEND
* COMMAND HAS EVOLVED INTO A CLASSIC
* CASE OF SPAGHETTI PROGRAMMING.
* PARTS OF THE FOLLOWING ROUTINES
* SEEM USELESS. THEY MAY JUST BE
* RESIDUAL (BUT INNOCUOUS) INSTRUCS
* THAT ARE LEFT OVER FROM AN EARLIER
* VERSION OF DOS.
* CHECK IF FILE POINTER AND WASTEBYT
* ARE ZEROES.
APNDPTCH LDY #$13
CK4ZEROS LDA (A4L),Y
BNE SETAPFLG ;UNLESS WE ARE DEALING WITH A
;USELESS FILE THAT WAS PREVIOUSLY
;OPENED. BUT NEVER CLOSED, THIS
;INSTRUCTION IS ALWAYS TAKEN.
INY
CPY #$17
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
* AN EMPTY FILE (IE. FILE WITH NO
* DATA) IS ENCOUNTERED.
LDY #$19 ;COPY IMAGE OF RECNMBWA/+1 AND
COPYRECS LDA (A4L),Y ;BYTOFFWA/+1 THAT WERE JUST
STA RECLENFM-$19,Y ;STORED IN THE WORK BUFFER TO
INY ;RECNMBFM/+1 AND BYTOFFFM/+1 IN
CPY #$1D ;THE FM PARAMETER LIST.
BNE COPYRECS
FMDVRTN JMP BK2FMDRV
* SET THE APPEND FLAG.
* (NEVER ENTERED IF DEALING WITH
* AN EMPTY FILE.)
SETAPFLG LDX #$FF
STX APPNDFLG ;SET THE APPEND FLAG.
BNE FMDVRTN ;ALWAYS.
*=================================
* YET ANOTHER APPEND PATCH.
* ($B6B3 - $B6CE)
*=================================
* BUGGY ROUTINE USED TO BACK UP THE
* FILE POINTER. IF A FILE IS $FFFF
* (#65536) BYTES LONG (OR SOME
* MULTIPLE THEREOF), THE APPEND CMD
* WILL FAIL BECAUSE THIS ROUTINE
* NEGLECTS TO BACK UP THE HI BYTE
* OF THE FILE POINTER (FILPTSEC+1).
RSETPTRS LDA RECNMBFM ;RECONCILE RECORD NUMBER VERSIONS
STA FILPTBYT ;AND LOWEST TWO BYTE OF THE FILE
STA RECNMBWA ;POINTER.
LDA RECNMBFM+1
STA WASTEBYT ;APPEARS TO BE IRRELEVANT.
;OBVIOUSLY HAS SOMETHING TO DO
;WITH CK4ZEROS ROUTINE DESCRIBED
;ABOVE.
STA RECNMBWA+1
STA FILPTSEC
TSX ;RESET THE STK POINTER SO WE CAN
STX STKSAV ;USE THE FMEXIT ROUTINE TO RETURN
;TO THE CALLER OF THE APPEND CMD.
;(NOTE: THIS WILL BE EXCEPTIONAL
;EXIT ROUTE FOR FMEXIT.)
JMP GOODFMXT ;EXIT THE APPEND CMD VIA FMEXIT
;ROUTINE. EXECUTION ACTUALLY RTNS
;2 AFTRCMD ($A17D) LOCATED IN THE
;CMD PARSING AND PROCESSING
;ROUTINES.
*=================================
* FREE SPACE
*=================================
DS 1 ;($B6CF)
*=================================
* STRAY CODE (NOT USED).
* ($B6D0-$B6E7.)
*=================================
* - DO A HOME & THEN PRINT "B01-00"
* - CONSIDER TO BE FREE SPACE.
JSR HOME
LDA #"B"
JSR COUT
LDA #$01
JSR PRBYTE
LDA #"-"
JSR COUT
LDA #$00
JSR PRBYTE
RTS
*=================================
* FREE SPACE
*=================================
DS 21 ;($B6E8-$B6FC.)
*=================================
* STORAGE FOR BOOT1.
* ($B6FD - $B6FF)
* (IMAGE MOVED TO $8FD-$8FF.)
*=================================
IMG8FD DA $B600 ;VARIES FROM $B600-$BF00 ON 48K
;SLAVE. (EVENTUALLY POINTS TO THE
;START OF BOOT2 AT $B700. IMAGE
;OF BT1LDADR AT $8FD.)
IMG8FF DS 1 ;CONTAINS # OF PAGES TO READ WHEN
;EXECUTING BOOT1. ALSO DOUBLES AS
;LOGICAL SEC#. INITIALLY = $01.
;VARIES FROM:$09 --> $00 --> $FF.
;(IMAGE OF BT1PG2RD AT $8FF.)
*=========================================
* BOOT2 ($B700 - $B749).
*=========================================
* - READS IN THE REST OF DOS STARING AT
* TRK02/SEC04 DOWN TO TRK00/SEC0A
* ($B5FF --> $9B00). (SECTORS 0A & 0B
* OF TRK 0 ($9CFF - $9B00) ARE
* EMPTY.)
* - AFTER THE REST OF DOS IS READ IN,
* EXECUTION JUMPS TO DOS'S COLDSTART
* ROUTINE (DOSCLD, $9D84).
* - NOTE THAT ON ENTRY: (X) = SLOT * 16.
*:::::::::::::::::::::::::::::::::::::::::
* PREPARE RWTS'S INPUT-OUTOUT BLOCK
* (IOB) AND DESIGNATE THE NUMBER OF
* SECTORS TO READ.
BOOT2 STX IBSLOT ;(X) = SLOT*16 WANTED.
STX IOBPSN ;LAST-USED SLOT*16.
LDA #1 ;DESIGNATE BOTH LAST-USED & WNTD
STA IOBPDN ;DRIVES TO BE DRIVE#1.
STA IBDRVN
LDA NMPG2RD ;SET NUMBER OF PAGES TO READ.
STA BT2PGCTR ;COUNTER 4 NUMBER OF PGS 2 READ.
LDA #2 ;START WITH TRK$02/SEC$04.
STA IBTRK ;TRACK.
LDA #4
STA IBSECT ;SECTOR.
LDY BT1MGADR+1 ;(Y)=HI BYTE OF ADDR OF IMAGE OF
;BOOT1 (#$B6 ON 48K SLAVE).
DEY ;DEFINE I/O BUF AS 1 PAGE BELOW
STY IBBUFP+1 ;BOOT1.
LDA #1 ;OPCODE FOR READ.
STA IBCMD
* CONVERT FROM (X) = SLOT*16
* TO (X) = SLOT.
TXA ;(X) = SLOT * 16.
LSR ;DIVIDE BY 16.
LSR
LSR
LSR
TAX ;(X) = SLOT.
* INITIALIZE PAGE-4 LOCATIONS WITH
* TRACK #'S ASSOC WITH THE DRIVES.
LDA #0
STA TRK4DRV2,X
STA TRK4DRV1,X
* CALL ROUTINE TO READ IN THE REST OF DOS.
JSR RWPAGES ;GO READ A GROUP OF PAGES (SECS).
LDX #$FF ;COMPLETELY CLEAR OUT THE STACK.
TXS
STX IBVOL ;SET VOL TO $FF (COMPLEMENT OF 0)
JMP CLOBCARD ;GO CLOBBER THE LANGUAGE CARD AND
;SET VIDEO OUTPUT (SIMUL8 PR#0).
;(RETURNS TO NEXT INSTRUC BELOW.)
BK2BOOT2 JSR SETKBD ;SIMULATE "IN#0" STATEMENT.
;(THAT IS, SELECT KEYBOARD.)
JMP DOSCOLD ;JUMP IN2 DOS'S COLDSTART ROUTINE
;(AT $9DE4) TO BUILD THE DOS BUFS
;AND THE PAGE-3 VECTOR TABLE AND
;THEN RUN THE "HELLO" PROGRAM.
;************* NOTE *************
;* THIS INSTRUC IS A HACKER'S *
;* DREAM. FOR INSTANCE, YOU CAN*
;* CHANGE THE JUMP TO POINT TO *
;* YOUR OWN PASSWORD OR TIME- *
;* BOMB PRGM THAT YOU HAVE *
;* DEVIOUSLY IMBEDDED IN AN *
;* UNUSED SECTION OF DOS. *
;********************************
*================================
* WRITE DOS IMAGE ON TRKS 0 - 2.
* (USED BY INIT FUNCTION.)
*
* WRITE TRK02/SEC04 ($B5FF) DOWN
* TO TRK00/SEC0C ($9D00).
*================================
WRDOSIMG LDA BTSTAGE+1 ;CALC # 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 ;SET WRITE COMMAND.
STA IBCMD
JSR RWPAGES ;WRT TRK02/SEC04 TO TRK00/SEC00.
* WRITE TRK00/SEC09 ($BFFF) DOWN
* TO TRK00/SEC00 ($9D00).
LDA BTSTAGE+1 ;STORE HI BYTE OF ADRRESS OF THE
STA IMG8FD+1 ;START OF BOOT1 (#$B6).
CLC ;CALC HI BYTE ADR OF TRK00/SEC09
ADC #9 ;(#$B6 + #$09 = #$BF).
STA IBBUFP+1 ;SET BUF 2 SEND INFO 2 PAGE #$BF.
LDA #10 ;DESIGNATE 10 PAGES TO WRITE.
STA BT2PGCTR ;(#$BFFF - #$B600).
SEC
SBC #1
STA IMG8FF ;SIGNIFY THAT THERE ARE 9 PAGES 2
;BE READ WHEN BOOT1 IS EXECUTED.
STA IBSECT ;START WRITING WITH TRK00/SEC09.
JSR RWPAGES ;WRITE TRK00/SEC09 2 TRK00/SEC00.
RTS
*================================*
* FREE SPACE ($B78D-$B792).
*================================*
HEX 000000000000 ;UNUSED.
*=================================
* READ/WRITE A GROUP OF PAGES.
*=================================
RWPAGES LDA ADROFIOB+1 ;INIT (A)/(Y) WITH HI/LOW BYTS OF
LDY ADROFIOB ;ADR OF RWTS'S IOB 4 NTRY 2 RWTS.
JSR ENTERWTS ;ENTER IN2 RWTS 2 READ/WRITE SEC.
LDY IBSECT ;GET # OF SEC JUST RD OR WRITTEN
DEY ;VAL 4 NXT SEC 2 READ/WRITE (WHEN
;EXECUTING BOOT1, #$09 --> #$FF).
BPL SAMETRK ;BRANCH TO USE THE SAME TRACK.
* START A NEW TRACK.
LDY #$0F ;START WITH SEC 15.
NOP
NOP
DEC IBTRK ;REDUCE TRK# WANTED.
* ADJUST POINTER TO IOB & TEST IF THERE
* ARE ANY MORE SECTORS TO READ/WRITE.
SAMETRK STY IBSECT ;STORE NUMBER OF SEC WANTED.
DEC IBBUFP+1 ;REDUCE BUFFER'S PAGE ADR.
DEC BT2PGCTR ;REDUCE CNTR 4 # OF SECS 2 READ.
BNE RWPAGES ;MORE SECS TO READ.
RTS
*===================================
* ROUTE EXECUTION TO RWTS.
*===================================
* NORMAL ROUTE TO ENTER RWTS FROM
* CUSTOM ASSEMBLY LANGUAGE PRGMS.
* ON ENTRY - THE IOB AND DCT TBLS
* MUST ALREADY BE SET UP.
* - (Y) AND (A) = LOW AND
* HI BYTES (RESPECTIVELY)
* OF ADDR OF IOB TABLE.
* (P.S. NOTE THAT THE $3D9 VECTOR
* JUMPS TO HERE!!!)
ENTERWTS PHP ;SAVE STATUS ON STK.
;(C)=0 IF SEEKING OR READING.
;(C)=1 IF WRITING OR FORMATTING.
SEI ;SET INTERRUPT DISABLE FLAG TO
;PREVENT ANY FURTHER MASKABLE
;INTERRUPTS WHEN DOING REAL-TIME
;PROGRAMMING.
JSR RWTS ;ENTER RWTS PROPER 2 DO OPERAT'N:
; $00=SEEK, $01=READ,
; $02=WRITE, $03=FORMAT.
BCS ERRENTER ;OPERATION WAS NOT SUCCESSFUL.
;NVR TAKEN IF JUST SEEKING CAUSE
;NO ERROR SIGNALLING ROUTINES ARE
;ASSOCIATED WITH THAT OPERATION.
PLP ;THROW STATUS OFF STACK.
CLC ;SIGNAL SUCCESSFUL.
RTS
ERRENTER PLP ;THROW STATUS OFF STACK.
SEC ;SIGNAL UNSUCCESSFUL.
RTS
*=================================
* SET UP RWTS'S IOB TO WRITE DOS.
*=================================
PRPWRDOS LDA FIRDOSPG+1 ;DESIGNATE START OF DOS AS ADR OF
STA IBBUFP+1 ;I/O BUF IN RWTS'S IOB.
LDA #0
STA IBBUFP
LDA VOLWA ;COMPLEMENT VOL#.
EOR #$FF
STA IBVOL
RTS
*=================================
* ZERO OUT THE CURRENT (256-BYTE)
* BUFFER.
*=================================
ZCURBUF LDA #0
TAY
ZCURBUF1 STA (A4L),Y
INY
BNE ZCURBUF1
RTS
*=================================
* PARAMETERS FOR BOOT2.
* ($B7DF - $B7E7)
*=================================
DS 1 ;UNUSED ($B7DF).
NMPG2RD HEX 1B ;# OF PAGES TO READ (#27).
BT2PGCTR DS 1 ;# OF PAGES LEFT 2 READ (VARIES).
BT1RSTSC HEX 0A ;FIRST SEC # IN STAGE (#10).
DS 1 ;UNUSED ($B7E3).
ADROFIOB DA IBTYPE ;ADR OF RWTS'S IOB (NORM $B7E8).
BTSTAGE DA SEC2RDB6 ;ADR OF START OF IMAGE OF BOOT1.
;(NORMALLY, $B600.)
BT1MGADR = BTSTAGE
*=================================
* RWTS'S INPUT/OUTPUT BLOCK (IOB).
* ($B7E8 - $B7FA)
*=================================
IBTYPE HEX 01 ;TABLE TYPE (SHOULD BE $01).
IBSLOT DS 1 ;SLOT WANTED * 16.
IBDRVN DS 1 ;DRIVE WANTED ($01 OR $02).
IBVOL DS 1 ;VOL WANTED ($00 GOOD FOR ALL).
IBTRK DS 1 ;TRK WANTED.
IBSECT DS 1 ;LOGICAL SEC WANTED.
IBDCTP DA DEVTPC ;PTS 2 DEVICE CHARACTERISTIC TBL.
;(NORMALLY, $B7FB).
IBBUFP DS 2 ;PTS 2 RWTS'S I/O BUFFER.
IBSECSZ HEX 0001 ;SEC SIZ IN BYTS (LOW/HI FORMAT).
IBCMD DS 1 ;RWTS COMMAND CODE:
; $00=SEEK, $01=READ,
; $02=WRITE, $04=FORMAT.
IBSTAT DS 1 ;ERROR CODE:
;$00=NO ERRS, $10=WRIT PROT,
;$20=VOL MISMTCH, $40=I/O(DRV)ERR
;$80=READ ERR.
IBSMOD DS 1 ;VOLUME FOUND.
IOBPSN DS 1 ;SLOT*16 OF LAST ACCESS (FOUND).
IOBPDN DS 1 ;DRIVE # OF LAST ACCESS (FOUND).
HEX 0000 ;UNUSED ($B7F9-$B7FA).
*=================================
* DEVICE CHARACTERISTIC TABLE.
* ($B7FB - $B7FF)
*=================================
DEVTPC HEX 00 ;DEVICE TYPE.
PPTC HEX 01 ;PHASES/TRK. (EVEN VAL = 1PHASE,
;ODD VAL = 2PHASE.) THEREFORE,
;$01=2 PHASE (WHICH TRANSLATES TO
;2 ARM MOVEMENTS PER TRACK).
MONTC HEX EFD8 ;MOTOR-ON-TIME COUNT.
DS 1 ;UNUSED ($B7FF).
D

View File

@@ -0,0 +1,917 @@
*================================
* PRENIBBLE DATA ($B800-$B829).
* CONVERT 256 MEMORY BYTES TO 342
* SIX-BIT NIBBLES AS SHOWN BELOW.
*================================
* ON ENTRY: PTR2BUF PTS AT DATA BUF.
* ON EXIT: (A) = ?.
* (X) = #$FF.
* (Y) = #$FF.
* (C) = 1.
* RWTSBUF1
* BB00: 0 0 00-7 00-6 00-5 00-4 00-3 00-2
* BB01: 0 0 01-7 01-6 01-5 01-4 01-3 01-2
* BB02: 0 0 02-7 02-6 02-5 02-4 02-3 02-2
* .
* .
* .
* BBFF: 0 0 FF-7 FF-6 FF-5 FF-4 FF-3 FF-2
*
* RWTSBUF2
* BC00: 0 0 01-0 01-1 AB-0 AB-1 55-0 55-1
* BC01: 0 0 00-0 00-1 AA-0 AA-1 54-0 54-1
* BC02: 0 0 FF-0 FF-1 A9-0 A9-1 53-0 53-1
* .
* .
* .
* BC54: 0 0 AD-0 AD-1 57-0 57-1 01-0 01-1
* BC55: 0 0 AC-0 AC-1 56-0 56-1 00-0 00-1
* WHERE "AC-0" = BIT0 OF MEMORY BYTE
* WHICH IS OFFSET
* #$AC BYTES INTO
* THE DATA SECTOR.
* THE FOLLOWING BITS ARE DUPLICATED
* IN $BC00-$BC01 & $BC54-$BC55 BUT
* ARE IGNORED IN $BC00-$BC01:
* 01-0,01-1,00-0,00-1.
PRENIBL LDX #0
LDY #2
PRENIB1 DEY
LDA (PTR2BUF),Y ;GET BYTE FROM "DATA" BUFFER.
LSR ;PUT ITS LWR 2 BITS IN2 RWTSBUF1.
ROL RWTSBUF2,X
LSR
ROL RWTSBUF2,X
STA RWTSBUF1,Y ;PUT REMAINING 6 BITS N RWTSBUF1.
INX
CPX #$56
BCC PRENIB1
LDX #0
TYA
BNE PRENIB1 ;REPEAT UNTIL @ BYTE OF RWTSBUF2
;HAS 6 BITS.
LDX #$55 ;MAKE SURE BITS 6 & 7 OF RWTSBUF2
PRENIB2 LDA RWTSBUF2,X ;ARE ZEROES.
AND #%00111111
STA RWTSBUF2,X
DEX
BPL PRENIB2
RTS
*====================================
* WRITE SECTOR TO DISK ($B82A-$B8B7).
*====================================
* ON ENTRY: (X) = SLOT*16
* ON EXIT: (C) = 1 = WRIT PROT ERR.
* IF NO ERROR: (C) = 0
* (A) = ?
* (X) = SLOT*16
* (Y) = #$00
WRITESEC SEC ;(C)=1, ASSUME WRITE PROTECTED
;ERROR AS DEFAULT CONDITION.
STX FRMTSLOT ;SAVE SLOT*16 IN PAGES 0 & 6.
STX SLOTPG6
LDA Q6H,X ;CHK IF DISK IS WRITE PROTECTED.
LDA Q7L,X
BMI PROTECTD ;BRANCH IF WRITE PROTECTED.
LDA RWTSBUF2 ;GET 1RST 2-ENCODED BYTE AND SAVE
STA HOLDNIBL ;IT FOR LATER USE.
* WRITE 5-SYNC GAP BETWEEN ADDRESS
* EPILOGUE & DATA PROLOGUE.
LDA #$FF ;(A) = SYNC BYTE.
STA Q7H,X ;WRITE 1 SYNC BYTE.
ORA Q6L,X
PHA ;(3 CYC)
PLA ;(4 CYC)
NOP ;(2 CYC)
LDY #4 ;WRITE 4 MORE SYNCS (2 CYC).
WRITE4FF PHA ;(3 CYC)
PLA ;(4 CYC)
JSR WRITE2 ;(12 CYC BEFORE, 6 AFTER.)
DEY ;(2 CYC)
BNE WRITE4FF ;(2 OR 3 CYC)
* WRITE DATA PROLOGUE ("D5 AA AD").
LDA #$D5 ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
LDA #$AA ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
LDA #$AD ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
* CONVERT & WRITE CONTENTS OF RWTS
* BUFFERS TO DISK. (WHEN FORMATTING,
* THESE BUFS ARE ZEROED OUT. THE
* "$00" BYTES IN BUF ARE LATER TRANS-
* LATED TO "$96" BYTES ON THE DISK.)
* CONVERT & WRITE 2-ENCODED
* NIBBLES FROM RWTSBUF2.
* (EOR TO CALC (X) & THEN USE (X)
* AS INDEX TO TBL OF DISK BYTES.)
*
* #0 EOR $BC55 = (X)
* $BC55 EOR $BC54 = (X)
* $BC54 EOR $BC53 = (X)
* . . . .
* . . . .
* . . . .
* $BC01 EOR $BC00 = (X)
TYA ;(A) = 0.
LDY #$56 ;(DEC #86.)
BNE DOEOR ;ALWAYS.
GETNIBL LDA RWTSBUF2,Y
DOEOR EOR RWTSBUF2-1,Y
TAX ;INDEX TO DISK BYTE.
LDA DSKNBTBL,X ;GET DISK BYTE.
LDX FRMTSLOT ;(X) = SLOT*16.
STA Q6H,X ;WRITE BYTE.
LDA Q6L,X
DEY ;(Y) = $56 --> #$00.
BNE GETNIBL ;(WRITE $56 OR DEC #86 BYTES.)
* CONVERT & WRITE 6-ENCODED
* NIBBLES FROM RWTSBUF1.
*
* $BC00 EOR $BB00 = (X)
* $BB00 EOR $BB01 = (X)
* $BB01 EOR $BB02 = (X)
* . . . .
* . . . .
* . . . .
* $BBFE EOR $BBFF = (X)
LDA HOLDNIBL ;NORMALLY = CONTENTS OF $BC00.
NOP
SCNDEOR EOR RWTSBUF1,Y
TAX ;INDEX TO DISK BYTE.
LDA DSKNBTBL,X ;GET DISK BYTE TO WRITE.
LDX SLOTPG6 ;(X) = SLOT*16.
STA Q6H,X ;WRITE 87TH ---> 341ST BYTES.
LDA Q6L,X
LDA RWTSBUF1,Y
INY ;(Y) = #$00 ---> #$FF.
BNE SCNDEOR
* CONVERT & WRITE DATA CHECKSUM.
* (342ND BYTE, $BBFF ------> (X).)
TAX ;INDEX TO TABLE OF DISK BYTES.
LDA DSKNBTBL,X ;GET DISK BYTE TO WRITE.
LDX FRMTSLOT ;(X) = SLOT*16.
JSR WRITE3 ;(5 CYCS BEFORE, 6 AFTER.)
* WRITE DATA EPILOGUE ("DE AA EB").
LDA #$DE ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
LDA #$AA ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
LDA #$EB ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
* WRITE A SYNC BYTE.
LDA #$FF ;(2 CYC)
JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
LDA Q7L,X ;SET READ MODE.
PROTECTD LDA Q6L,X
RTS
*====================================
* WRITE BYTE WITH VARIOUS DELAYS.
* (DELAYS PRIOR TO ENTRY & THOSE
* SHOWN BELOW RESULT IN WRITING BYTES
* EVERY 32 MACHINE CYCLES.)
*====================================
WRITE1 CLC ;(2 CYC)
WRITE2 PHA ;(3 CYC)
PLA ;(4 CYC)
WRITE3 STA Q6H,X ;(5 CYC) - SHIFT REGISTER)
ORA Q6L,X ;(4 CYC - STROBE LATCH)
RTS ;(6 CYC)
*=================================
* POSTNIBBLE DATA ($B8C2 - $B8DB).
* CONVERT 6- & 2-ENCODED BYTES IN
* RWTS'S TWO BUFFERS TO NORMAL
* MEMORY BYTES (USUALLY PLACED IN
* DOS DATA SECTOR BUFFER).
*=================================
* ON ENTRY: (X) = SLOT*16.
* PTR2BUF = PTS TO DATA BUF.
* ON EXIT: (A) = ?
* (X) = ?
* (Y) = BYTE COUNT USED
* FOR RWTBUF2.
* (C) = 1.
POSTNB16 LDY #0
POSTNIB1 LDX #$56 ;(DEC #86.)
POSTNIB2 DEX
BMI POSTNIB1
LDA RWTSBUF1,Y ;SET (A) = 6-ENCODED BYTE.
LSR RWTSBUF2,X ;PUT LWR 2 BITS OF 2-ENCODED BYTE
ROL ;INTO ORIGNAL 6-ENCODED BYTE TO
LSR RWTSBUF2,X ;CREATE A NORMAL MEMORY BYTE.
ROL
STA (PTR2BUF),Y ;PUT NORMAL MEMORY BYTE IN RWTS'S
INY ;BUF (NORMALLY DOS DATA SEC BUF).
CPY PROSCRTH
BNE POSTNIB2
RTS
*===================================
* READ DATA SECTOR INTO RWTS'S BUFS.
*===================================
* CONDITIONS FOR $B8DC - $B943:
* ON ENTRY: (X) = SLOT*16
* ON EXIT: (C) = 1 IF ERROR
* IF NO ERR: (C) = 0.
* (A) = #$AA.
* (X) = SLOT*16.
* (Y) = #$00.
* FIND DATA PROLOGUE ("D5 AA AD").
READATA LDY #32 ;SET (Y) = 32 ATTEMPTS TO FIND
REDUCEY DEY ;THE DATA PROLOGUE.
BEQ ERRTN ;ERROR - CAN'T FIND DAT PROLOGUE.
PRODATD5 LDA Q6L,X ;GET BYTE FROM DATA PROLOGUE.
BPL PRODATD5 ;WAIT FOR FULL BYTE.
VERSD5 EOR #$D5 ;CHK IF BYTE WAS "D5".
BNE REDUCEY ;WASN'T "D5", REDUCE COUNTER.
NOP ;STALL 2 CYCLES.
PRODATAA LDA Q6L,X ;READ NEXT DATA PROLOGUE BYTE.
BPL PRODATAA ;WAIT FOR FULL BYTE.
CMP #$AA ;WAS IT AN "AA"?
BNE VERSD5 ;NO - GO RESTART SEQUENCE.
LDY #$56 ;SET (Y) FOR LATER USE IN READ
;DATA ROUTINE.
PRODATAD LDA Q6L,X ;READ NEXT BYTE IN DATA PROLOGUE.
BPL PRODATAD ;WAIT FOR FULL BYTE.
CMP #$AD ;WAS IT AN "AD"?
BNE VERSD5 ;NO - GO RESTART SEQUENCE.
* READ 1RST 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.
* (IE. WE ARE JUST DOING OPPOSITE
* OF WRITING.)
* EOR VALUE FROM NDX2NIBL TABLE
* WITH PREVIOUS EOR RESULT. (ON
* ENTRY, USE #$00 FOR PREVIOUS
* EOR RESULT.)
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 FULL BYTE.
EOR NDX2NIBL-$96,Y ;USE (Y) AS INDEX TO TABLE OF
;2-ENCODED NIBBLES.
LDY PROSCRTH ;RETRIEVE INDEX TO SECOND BUF.
STA RWTSBUF2,Y ;STORE 2-ENCODED NIBL N RWTSBUF2.
BNE RDUCY ;Z-FLG CONDITIONED FRM THE "LDY".
* READ REST OF SEC 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.
* (IE. WE ARE JUST DOING OPPOSITE
* OF WRITING.)
* EOR VALUE FROM NDX2NIBL TABLE
* WITH PREVIOUS EOR RESULT.
SAVYNDX STY PROSCRTH ;SAVE INDEX TO RWTSBUF1.
RDSKBYT2 LDY Q6L,X ;(Y) = DISK BYTE.
BPL RDSKBYT2 ;WAIT FOR FULL BYTE.
EOR NDX2NIBL-$96,Y ;GET 6-ENCODED NIBL FRM TBL.
LDY PROSCRTH ;GET INDEX TO RWTSBUF1.
STA RWTSBUF1,Y ;STORE 6-ENCODED NIBL N RWTSBUF1.
INY
BNE SAVYNDX ;MORE DISK BYTES TO READ.
* READ DATA CHECKSUM.
RDCHECK LDY Q6L,X ;GET DATA CHECKSUM BYTE FROM DSK.
BPL RDCHECK ;WAIT FOR FULL BYTE.
CMP NDX2NIBL-$96,Y ;DOES CONVERTED CHKSUM EQUAL
;THE VALUE 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!!!
BNE ERRTN ;ERROR -DIDN'T MATCH WITH CHKSUM.
;HACKERS OFTEN CHANGE THESE TWO
;BYTES 2 "CLC" AND "RTS" INSTRUCS
;IN ORDER TO DEFEAT DATA CHECKSUM
;AND IGNORE THE DATA EPILOGUE.
* READ 1RST TWO BYTES (ONLY) OF
* DATA EPILOGUE ("DE AA EB").
EPIRDDE LDA Q6L,X ;READ 1RST BYTE OF DATA EPILOGUE.
BPL EPIRDDE ;WAIT FOR FULL BYTE.
CMP #$DE ;IS IT A "DE"?
BNE ERRTN ;NO - GOT AN ERROR.
NOP ;STALL 2 CYCLES.
EPIRDAA LDA Q6L,X ;READ 2ND BYTE OF DATA EPILOGUE.
BPL EPIRDAA ;WAIT FOR FULL BYTE.
CMP #$AA ;IS IT AN "AA"?
BEQ GOODRTN ;YES - GOT A GOOD READ.
ERRTN SEC ;SIGNAL BAD READ.
RTS ;HACKERS OFTEN CHANGE THE "SEC" 2
;"CLC" TO DEFEAT ERROR CHECKING.
*====================================
* READ ADDRESS ROUTINE ($B944-$B99F).
*====================================
* ON ENTRY: (X) = SLOT*16.
* ON EXIT: (C) = 1 IF ERROR.
* IF NO ERRS: (A) = #$AA.
* (Y) = #$00.
* (X) = SLOT*16.
* $2C = CHECKSUM VAL FOUND.
* $2D = SEC # FOUND.
* $2E = TRK # FOUND.
* $2F = VOL # FOUND.
* READ THE ADDRESS HEADER.
RDADDR LDY #$FC ;SET 772 CHANCES TO FIND CORRECT
STY PROSCRTH ;ADR PROLOGUE (#$FCFC-#$10000).
KICKNTR INY
BNE TRYD5
INC PROSCRTH
BEQ ERRTN ;ERROR - CAN'T FIND PROLOGUE.
* FIND ADR PROLOGUE ("D5 AA 96").
TRYD5 LDA Q6L,X
BPL TRYD5 ;WAIT FOR A FULL BYTE.
VERSUSD5 CMP #$D5 ;WAS IT "D5"?
BNE KICKNTR ;NO - TRY AGAIN.
NOP ;WAIT 2 CYCLES.
TRYAA LDA Q6L,X
BPL TRYAA ;WAIT FOR FULL BYTE.
CMP #$AA ;WAS IT "AA"?
BNE VERSUSD5 ;NO - RETRY SEQUENCE.
LDY #3 ;SET (Y) 4 LATER READING OF VOL,
;TRK, SEC & CHKSUM INFO FROM THE
;ADRRESS FIELD.
TRY96 LDA Q6L,X
BPL TRY96 ;WAIT FOR A FULL BYTE.
CMP #$96 ;WAS IT "96"?
BNE VERSUSD5 ;NO - RETRY SEQUENCE.
* READ ODD-EVEN ENCODED VOL, TRK,
* SEC & CHECKSUM FROM ADR FIELD.
* (DURING READING, CALC A RUNNING
* CHECKSUM.)
* FROM: BYTE1: 1 B7 1 B5 1 B3 1 B1
* BYTE1: B6 1 B4 1 B2 1 B0 1
* ---------------------------------
* TO: BYTE: B7 B6 B5 B4 B3 B2 B1 B0
LDA #0 ;INTIALIZE FOR RUNNING CHECKSUM.
CALCK STA CKSUMCAL
GETHDR LDA Q6L,X ;GET ODD-ENCODED BYTE.
BPL GETHDR ;WAIT FOR A FULL BYTE.
ROL ;SHIFT BITS, PUT (C)=1 IN BIT0.
STA PROSCRTH ;SAVE SHIFTED VERSION.
RDHDR LDA Q6L,X ;GET EVEN-CODED BYTE.
BPL RDHDR ;WAIT FOR A FULL BYTE.
AND PROSCRTH ;MERGE & CREATE NORM MEMORY BYTE.
STA: CKSUMDSK,Y ;STORE INFO READ FROM ADDR FIELD
;IN Z-PAGE:
;2F = VOL FND, 2E = TRK FND,
;2D = SEC FND, 2C = CHECKSUM FND.
;(NOTE "STA:" FORCES 3-BYT CODE.)
EOR CKSUMCAL ;UPDATE RUNNING CHECKSUM.
DEY
BPL CALCK
TAY ;PUT CHECKSUM FOUND IN (Y).
BNE ERRTN ;IF CHKSUM FOUND < > 0 THEN ERR.
;HACKERS OFTEN CHANGE THESE TWO
;BYTES 2 "CLC" AND "RTS" INSTRUCS
;IN ORDER 2 DEFEAT THE ADR CHKSUM
;AND IGNORE THE ADR EPILOGUE.
* READ 1RST 2 BYTES (ONLY) OF
* ADDRESS EPILOGUE ("DE AA EB").
TRYEPIDE LDA Q6L,X ;GET 1RST 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 2ND BYTE.
BPL TRYEPIAA ;WAIT FOR A FULL BYTE.
CMP #$AA ;WAS IT AN "AA"?
BNE ERRTN ;NO - RETRY SEQUENCE.
GOODRTN CLC ;SIGNAL GOOD READ.
RTS
*======================================
* MOVE DISK ARM TO A GIVEN HALFTRACK
* POSITION ($B9A0-$B9FF).
*======================================
* ON ENTRY: (X) = SLOT*16
* (A) = DESTINATION HALFTRK.
* PRESTRK = CURRENT HALFTRK.
* ON EXIT: (A) = ?
* (X) = SLOT*16.
* (Y) = ?
* DESTRK = FINAL HALFTRK.
* PRESTRK = FINAL HALFTRK.
* HOLDPRES = PREVIOUS HALFTRK.
SEEKABS STX SLT16ZPG ;SAVE SLOT*16 IN ZERO PAGE.
STA DESTRK ;SAVE DESTINATION HALFTRK#.
CMP PRESTRK ;DESTINATION 1/2TRK=PRES 1/2TRK?
BEQ ARRIVED ;YES-WE'RE ALREADY THERE, SO XIT.
LDA #0 ;INIT COUNTER 4 # OF TRKS MOVED.
STA STPSDONE
* SAVE CURRENT HALFTRK POS'N AND CALC #
* OF HALFTRKS NEED TO MOVE MINUS 1.
SAVCURTK LDA PRESTRK ;SAVE CURRENT HALFTRK POSITON.
STA HOLDPRES
SEC ;CALC (PRESTRK-DESTRK).
SBC DESTRK
BEQ ATDESTN ;AT DESTINATION SO GO SHUTDOWN.
BCS MOVDOWN ;PRES 1/2TRK > DESTINATION 1/2TRK
;SO WANT 2 MOVE 2 LOWER 1/2TRK#.
* WANT TO MOVE TO HIGHER HALFTRK#.
* (PRESTRK - DESTRK = NEG RESULT.)
EOR #$FF ;CONVERT NEG TO POS.
INC PRESTRK ;MOVING UP,SO INC CURRENT HALFTRK
;POS'N FOR NEXT TIME AROUND.
BCC CKDLYNDX ;ALWAYS.
* WANT TO MOVE TO LOWER HALFTRK#.
* (PRESTRK - DESTRK = POS RESULT.)
MOVDOWN ADC #$FE ;SIMULATE A SUBTRATION OF 1.
;ACTUALLY ADDING MINUS 1 (#$FF)
;CAUSE (C)=1. WANT (A) TO EQUAL
;1 LESS THAN # OF HALFTRKS 2 MOV.
DEC PRESTRK ;MOVING DOWN, REDUCE PRES HALFTRK
;NUMBER FOR NEXT TIME AROUND.
* CHECK TO SEE WHICH INDEX TO USE
* TO ACCESS THE DELAY TABLE. IF
* WE ARE WITHIN 12 STEPS OF THE
* DESTINATION OR START POS'NS, USE
* CLOSEST DISTANCE TO START OR END
* POS'N TO INDEX THE DELAY TABLES.
* DELAY TABLES ARE ONLY 12 BYTES
* LONG, SO IF MORE THAN 12 STEPS
* AWAY FROM BOTH START & DEST'N,
* USE LAST INDEX (Y=12) TO ACCESS
* THE TABLE.
* CHECK IF CLOSER TO DEST'N OR
* START POS'N.
CKDLYNDX CMP STPSDONE ;COMPARE # OF HALFTRKS ALREADY
;MOVED VS # HALFTRKS NEED 2 MOVE.
BCC CLSR2ND ;CLOSER TO DEST'N THAN START.
* CLOSER TO START.
LDA STPSDONE ;(A) = DISTANCE FROM START POS'N.
* ENTRY PT IF CLOSER TO END.
CLSR2ND CMP #12 ;ARE WE WITHIN 12 STEPS OF START
;OR DESTINATION POS'N?
BCS TURNON ;WE ARE AT OR BEYOND 12 STEPS FRM
;START OR DEST'N POS'N SO USE OLD
;INDEX TO ACCESS DELAY TABLE.
PRESNDX TAY ;USE PRES DISTANCE 2 INDEX TABLE.
TURNON SEC ;(C)=1 SO GET ODD INDEX TO BASE
;ADR SO MAGNET WILL BE TURNED ON.
JSR ONOROFF ;TURN MAGNET ON TO SUCK STEPPER
;MOTOR 2 CORRECT HALFTRACK POS'N.
LDA ONTABLE,Y ;GET TIME TO LEAVE MAGNET ON.
JSR DELAY ;DELAY TO GIVE DRIVE TIME TO ACT
;BEFORE MAGNET TURNED OFF AGAIN
;CAUSE COMPUTER IS TOO FAST FOR
;PERIPHERAL & WANT SMOOTH MOV'T.
LDA HOLDPRES ;(A) = LAST HALFTRK POS'N.
CLC ;CLR (C) SO INDEX WILL COME OUT
;EVEN & THERE4 MAGNET WILL BE
;TURNED OFF.
JSR ENTRYOFF ;TURN OFF THE MAGNET ASSOC WITH
;PREVIOUS POS'N.
LDA OFFTABLE,Y ;GET TIME TO LEAVE MAGNET OFF.
JSR DELAY ;LEAVE MAGNET OFF FOR A WHILE TO
;GIVE ARM TIME TO BE PROPERLY
;ALIGNED. (NEED TIME TO SUCK IT
;OVER & ALSO TO DECREASE BOUNCE
;OR OVER SHOOT.)
INC STPSDONE
BNE SAVCURTK ;ALWAYS.
*----------------------------------
* ARRIVED AT DESTINATION HALFTRACK.
*----------------------------------
ATDESTN JSR DELAY ;WAIT ON PERIPHERAL AGAIN.
* TURN LAST-USED MAGNET OFF SO EXIT
* WITH ALL PHASES (IE.MAGNETS) OFF.
* NOTE: THIS IS VERY IMPORTANT
* CAUSE MAG1ON IS WIRED INTO THE
* WRITE-PROTECT SWITCH!!!
CLC ;CLR (C) SO NDX WILL COME OUT AS
;EVEN & THERE4 MAGNET WILL BE
;TURNED OFF.
*---------------------------------
* TURN MAGNET ON OR OFF.
*---------------------------------
ONOROFF LDA PRESTRK ;USE HALFTRK POS'N 2 INDEX MAGNET
ENTRYOFF AND #%00000011 ;ONLY KEEP LWR 2 BITS OF HALFTRK#
;BECAUSE ONLY 4 MAGNETS (0,1,2,3)
ROL ;MULTIPLY HALFTRK * 2 & ADD (C).
;IF (C)=0, RESULT EVEN, MAG OFF
;IF (C)=1, RESULT ODD, MAGNET ON.
ORA SLT16ZPG ;MERGE INDEX 2 MAGNET WITH SLOT#.
TAX ;USE (X) TO INDEX MAGNET ON/OFF.
LDA MAG0FF,X ;USE MAGNET-0-OFF AS BASE ADR.
LDX SLT16ZPG ;RESTORE (X) = SLOT*16.
ARRIVED RTS
*=================================
* FREE SPACE ($B9FD-$B9FF).
*=================================
HEX AAA0A0 ;UNUSED.
*==================================
* MAIN DELAY ROUTINE IN DOS.
* AMT OF DELAY = 100*(A) MICROSECS.
*==================================
DELAY LDX #17
DLY1 DEX
BNE DLY1
INC MTRTIME
BNE DLY2
INC MTRTIME+1
DLY2 SEC
SBC #1
BNE DELAY
RTS
*=================================
* DELAY TIMES FOR STEPPER MOTOR
* MOVEMENTS. (VALUE * 100 = DELAY
* IN MICROSECONDS.)
*=================================
*---------------------------------
* TIMES TO LEAVE MAGNET ON.
* ($BA11 - $BA1C)
*---------------------------------
ONTABLE HEX 01302824201E1D1C1C1C1C1C
*---------------------------------
* TIMES TO LEAVE MAGNET OFF.
* ($BA1D - $BA28)
*---------------------------------
OFFTABLE HEX 702C26221F1E1D1C1C1C1C1C
*=================================
* TABLE OF DISK BYTES.
* ($BA29 - $BA68)
*=================================
DSKNBTBL HEX 96979A9B9D9E9F
HEX A6A7ABACADAEAF
HEX B2B3B4B5B6B7B9BABBBCBDBEBF
HEX CBCDCECF
HEX D3D6D7D9DADBDCDDDEDF
HEX E5E6E7E9EAEBECEDEEEF
HEX F2F3F4F5F6F7F9FAFBFCFDFEFF
*=================================
* CHECK IF USING APPEND CMD.
* (RECENT PATCH, $BA69-$BA75)
*=================================
* RAN OUT OF DATA SO BETTER CHECK
* IF WE ARE APPENDING.
CKIFAPND LDX NDX2CMD ;GET COMMAND INDEX.
CPX #$1C ;ARE WE APPENDING?
BEQ RTNCKAPN ;YES - LEAVE APPEND FLAG ON.
LDX #0 ;NO - MAKE SURE APPEND FLG OFF.
STX APPNDFLG
RTNCKAPN RTS
*=================================
* CLOBBER THE 80-COLUMN CARD.
* (RECENT PATCH, $BA76-$BA83)
*=================================
CONTCLOB LDA #$FF ;SET MODE FLAG FOR CARD.
STA $4FB ;SCRATCH PAD MEMORY FOR SLOT3.
STA $C00C ;TURN OFF THE ALTERNATE CHAR SET.
STA $C00E
JMP INIT ;SIMULATE A TEXT STATEMENT.
*=================================
* FREE SPACE
* ($BA84 - $BA95)
*=================================
DS 18
*==================================
* TABLE OF BYTES USED WHEN READING.
* ($BA96 - $BAFF)
* - USED TO TRANSLATE A DISK BYTE
* TO A 2- OR 6-ENCODED NIBBLE
* NEEDED FOR THE RWTS BUFFERS).
*==================================
* NUMBERS > $3F REPRESENT ILLEGAL
* DISK BYTES VALUES THAT ARE SIMPLY
* USED AS SPACERS IN TABLE.
NDX2NIBL HEX 0001 ; VALID INDICES.
HEX 9899 ; 2 SPACERS.
HEX 0203 ; VALID INDICES.
HEX 9C ; 1 SPACER.
HEX 040506 ; VALID INDICES.
HEX A0A1A2A3A4A5 ; 6 SPACERS.
HEX 0708 ; VALID INDICES.
HEX A8A9AA ; 3 SPACERS.
HEX 090A0B0C0D ; VALID INDICES.
HEX B0B1 ; 2 SPACERS.
HEX 0E0F10111213 ; VALID INDICES.
HEX B8 ; 1 SPACER.
HEX 1415161718191A ; VALID INDICES.
HEX C0C1C2C3C4C5 ; 6 SPACERS.
HEX C6C7C8C9CA ; 5 SPACERS.
HEX 1B ; VALID INDEX.
HEX CC ; 1 SPACER.
HEX 1C1D1E ; VALID INDICES.
HEX D0D1D2 ; 3 SPACERS.
HEX 1F ; VALID INDEX.
HEX D4D5 ; 2 SPACERS.
HEX 2021 ; VALID INDICES.
HEX D8 ; 1 SPACER.
HEX 22232425262728 ; VALID INDICES.
HEX E0E1E2E3E4 ; 5 SPACERS.
HEX 292A2B ; VALID INDICES.
HEX E8 ; 1 SPACER.
HEX 2C2D2E2F303132 ; 7 INDICES.
HEX F0F1 ; 2 SPACERS.
HEX 333435363738 ; VALID INDICES.
HEX F8 ; 1 SPACER.
HEX 393A3B3C3D3E3F ; VALID INDICES.
*=================================
* BUFFER ($BB00-BBFF) OF 6-ENCODED
* NIBBLES (IE. 00XXXXXX, WHERE
* X = 0 OR 1, BITS 6 & 7 ARE
* ALWAYS 0).
* USED AS A TRANSITION BUFFER
* BETWEEN NORMAL MEMORY BYTES
* AND DISK BYTES.
*=================================
RWTSBUF1 DS 256
*==================================
* BUFFER ($BC00-$BC55) OF 2-ENCODED
* NIBBLES.
*==================================
* NIBBLES ARE OF THE FORM:
* 0 0 JJ-0 JJ-1 KK-0 KK-1 LL-0 LL-1
* WHERE BITS 6 & 7 ARE ALWAYS 0.
* HOWEVER THE OTHER BITS REPRESENT
* A MIXTURE OF BITS FROM DIFFERENT
* ORIGINAL MEMORY BYTES.
* (IE. JJ-0 REPRESENTS BIT 0 FROM
* ORIGINAL MEMORY BYTE JJ.)
RWTSBUF2 DS 86
*======================================
* WRITE ADDRESS HEADER ($BC56-$BCC3).
* (ONLY USED BY RWTS'S FORMAT COMMAND).
*======================================
* ON ENTRY: (X) = SLOT*16.
* (Y) = # OF SELF SYNCS
* TO WRITE.
* HOLDAA = #$AA.
* FRMTSEC = SEC #.
* FRMTVOL = VOL #.
* FRMTKCTR = TRK #.
* ON EXIT: (A) = ?
* (X) = SLOT*16.
* (Y) = #$00.
* (C) = 0 IF NOT PROTECTED.
* = 1 IF WRITE PROTECTED.
WRITADR SEC ;(C)=1, ASSUME ERROR AS DEFAULT.
LDA Q6H,X ;CHK IF DISK IS WRITE PROTECTED.
LDA Q7L,X
BMI SET4RD ;BRANCH IF WRITE PROTECTED.
* NOT WRITE PROTECTED SO PREP TO
* WRITE A GAP OF 40-CYCLE SYNC
* BYTES BTWN SECS. (THIS ROUTINE
* WRITES 2 DIF SIZES OF GAPS. GAP1
* PRECEEDS SEC $00. IT INITIALLY
* CONSISTS OF 128 SELF-SYNC BYTES
* BUT IS LATER PARTIALLY OVER-
* WRITTEN BY SEC $0F. GAP3 OCCURS
* BTWN THE ADDR FIELD OF THE
* PRECEEDING SEC & THE DATA FIELD
* OF THE NEXT SEC. ITS LENGTH
* VARIES WITH THE TRK # AND THE
* SPEED OF THE SPECIFIC DRIVE
* BEING USED.)
LDA #$FF ;(A) = SYNC BYTE.
STA Q7H,X ;SET WRITE MODE.
CMP Q6L,X
PHA ;(3 CYC)
PLA ;(4 CYC)
WRTSYNC JSR WTADDRTN ;(12 CYC)
JSR WTADDRTN ;(12 CYC)
STA Q6H,X ;(5 CYC)
CMP Q6L,X ;(4 CYC), WRITE BYTE.
NOP ;(2 CYC)
DEY ;(2 CYC)
BNE WRTSYNC ;(3 CYC ON BRNCH, 2 ON FALL THRU)
* WRITE ADDRESS PROLOGUE.
* ("D5 AA 96", 32-CYCLE BYTES.)
LDA #$D5 ;(2 CYC)
JSR WRBYTE3 ;(24 CYC BEFORE, 6 AFTER)
LDA #$AA ;(2 CYC)
JSR WRBYTE3 ;(24 CYC BEFORE, 6 AFTER)
LDA #$96 ;(2 CYC)
JSR WRBYTE3 ;(24 CYC BEFORE, 6 AFTER)
* WRITE VOL, TRK & SECTOR AS
* ODD/EVEN ENCODED BYTES.
* (32 CYCLES BETWEEN BYTES.)
LDA FRMTVOL ;(A) = VOLUME #, (3 CYC).
JSR WRBYTE1 ;WRITE BYTES FOR VOLUME.
;(JSR INSTRUCTION = 6 CYC.)
LDA FRMTKCTR ;WRITE BYTES FOR TRK.
;(3 CYC + 6 FROM BEFORE.)
JSR WRBYTE1 ;(6 CYC + 17 MORE CYC, WITH
;6 RESIDUAL CYC.)
LDA FRMTSEC ;WRITE BYTES FOR SEC.
JSR WRBYTE1 ;(CYCLES AS PER ABOVE.)
* CALCULATE ADDRESS CHECKSUM.
LDA FRMTVOL ;(3 CYC + 6 FROM BEFORE)
EOR FRMTKCTR ;(3 CYC)
EOR FRMTSEC ;(3 CYC)
PHA ;SAVE CKSUM ON STK (3 CYC).
* ODD ENCODE THE ADDRESS CHECKSUM.
LSR ;(2 CYC)
ORA HOLDAA ;(3 CYC)
STA Q6H,X ;(5 CYC - WRITE BYTE)
LDA Q6L,X ;(4 CYC)
* EVEN ENCODE THE ADDRESS CHECKSUM.
PLA ;(3 CYC)
ORA #%10101010 ;(2 CYC)
JSR WRBYTE2 ;(26 CYC BEFORE WRITE, 6 AFTER)
* WRITE ADDRESS EPILOGUE.
* ("DE AA EB", 32-CYCLE BYTES.)
LDA #$DE ;(2 CYC + 6 LEFT OVER FRM B4.)
JSR WRBYTE3 ;(24 CYC BEFORE WRITE, 6 AFTER)
LDA #$AA ;(2 CYC + 6 LEFT OVER FROM B4)
JSR WRBYTE3 ;(24 CYC B4 WRITE, 6 LFT OVER)
LDA #$EB ;(2 CYC + 6 LEFT OVER FROM B4)
JSR WRBYTE3 ;(24 CYC BEFORE WRITE, 6 AFTER)
CLC
SET4RD LDA Q7L,X ;SET READ MODE.
LDA Q6L,X
WTADDRTN RTS
*=================================
* WRITE DOUBLE AND SINGLE BYTE
* SUBR'TNS WITH DIFFERENT DELAYS.
*=================================
* NOTE: A "JSR" INSTRUCTION
* REQUIRES 6 CYCLES. THEREFORE
* 6 CYCLES + ANY OTHER OVERHEAD
* SHOULD BE ADDED TO THE SUBRTNS
* GIVEN BELOW IN ORDER TO ARRIVE
* AT A 32-CYCLE COUNT BETWEEN @
* BYTE WRITTEN.
WRBYTE1 PHA ;(3 CYC)
* CALC & WRITE ODD-ENCODED BYTE.
LSR ;(2 CYC)
ORA HOLDAA ;(3 CYC)
STA Q6H,X ;(5 CYC)
CMP Q6L,X ;(4 CYC)
* CALC & WRITE EVEN-ENCODED BYTE.
PLA ;(4 CYC)
NOP ;(2 CYC)
NOP ;(2 CYC)
NOP ;(2 CYC)
ORA #$AA ;(2 CYC)
WRBYTE2 NOP ;(2 CYC)
WRBYTE3 NOP ;(2 CYC)
PHA ;(3 CYC)
PLA ;(4 CYC)
STA Q6H,X ;(5 CYC)
CMP Q6L,X ;(4 CYC)
RTS ;(6 CYC LEFT OVER AFTER WRITE)
*=================================
* FREE SPACE
* ($BCDF - $BCFF)
*=================================
DS 33 ;UNUSED GARBAGE - CONSIDER FREE.

View File

@@ -0,0 +1,978 @@
*=================================
* READ/WRITE TRACK/SECTOR (RWTS).
* (ENTER WITH (Y)/(A) POINTING AT
* RWTS'S INPUT/OUTPUT BLOCK (IOB).
*=================================
RWTS STY PTR2IOB ;SET UP A Z-PG PTR 2 RWTS'S IOB.
STA PTR2IOB+1
LDY #2 ;INITIALIZE CNTR FOR MAXIMUM
STY RECLBCNT ;NUMBER OF RECALIBRATION TRIES.
LDY #4 ;INITIALIZE COUNTER FOR MAXIMUM
STY RSEEKCNT ;# OF RE-SEEKS BTW'N RECALIBS.
LDY #1 ;(Y) = INDEX TO RWTS'S IOB.
LDA (PTR2IOB),Y ;GET SLOT*16 FROM IOB IN (X), SO
TAX ;CAN USE IT TO INDEX BASE ADRS
;FOR DRIVE FUNCTIONS.
* CHK IF WANTED SLOT*16 = LAST SLOT*16?
LDY #15 ;INDEX 4 VAL OF LAST SLOT USED.
CMP (PTR2IOB),Y ;WANTED*16 VS LAST*16.
BEQ SAMESLOT ;SLOT WANTED=SLOT LAST ACCESSED.
* WANT TO USE A DIFFERENT SLOT SO
* RESET (X) BACK TO INDEX OLD SLOT
* SO CAN TEST OLD MOTOR.
TXA ;SAVE SLOT*16 WANTED ON STK.
PHA
LDA (PTR2IOB),Y ;GET OLD SLOT*16 BACK.
TAX ;PUT IT IN (X) 2 INDEX BASE ADRS.
PLA ;PUT SLOT*16 WANTED IN (A) AND
PHA ;KEEP IT SAVED ON STK.
STA (PTR2IOB),Y ;UPDATE LAST-USED SLOT*16 FOR
;NEXT TIME AROUND.
* CHECK TO SEE IF LAST-USED DRIVE
* ASSOC WITH LAST-USED SLOT IS
* STILL SPINNING. IF IT IS, WAIT
* FOR IT TO STOP.
LDA Q7L,X ;PREP LATCH FOR INPUT.
CKSPIN LDY #8 ;SET CNTR 2 INSURE AT LEAST 8 CKS
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
BNE CHKCHNG ;DELAYS JUST TO MAKE SURE.
* GET INDEX FOR SLOT WANTED.
PLA ;GET SLOT*16 BAK OFF STK & PUT IT
TAX ;IN (X) SO WE CAN NDX BASE ADRS.
* CHECK TO SEE IF A DRIVE ASSOC
* WITH SLOT WANTED IS STILL
* SPINNING. (AS SOON AS GET A
* CHANGE, KNOW IT IS SPINNING.
* IF NO CHANGE, CHK AT LEAST 8
* TIMES TO BE CERTAIN IT IS OFF.)
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 WANTED IN PAGE5.
CMP Q6L,X ;HAS DATA CHANGED YET?
BNE DONETEST ;YES - DATA CHANGED, SO SPINNING.
DEY ;NO - NO CHANGE, SEE IF CHKD
;ENOUGH TIMES YET.
BNE STRBAGN ;CHK AT LEAST 8 TIMES.
DONETEST PHP ;SAVE TEST RESULTS ON STK SO CAN
;LATER 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 INSTRUC TO SEND POWER VIA
* THE CONTROLLER. ONCE SWITCH IS
* THROWN, WE CAN LATER RE-ROUTE
* THAT POWER TO WHICHEVER DRIVE WE
* WANT BY THROWING ANOTHER SWITCH
* TO SELECT DRIVE1 OR DRIVE2.
LDA MTRON,X ;TURN MOTOR ON.
* ESTABLISH Z-PAGE POINTERS TO
* DEVICE CHARACTERISTIC TABLE &
* RWTS'S I/O BUFFER (SO WE CAN
* USE Z-PAGE INDIRECT ADDRESSING):
* IBDCTP --> PTR2DCT (3C,3D).
* IBBUFP --> PTR2BUF (3E,3F).
LDY #6
MOVPTRS LDA (PTR2IOB),Y ;GET PTRS FROM RWTS'S IOB.
STA: PTR2DCT-6,Y ;PUT THEM IN Z-PAGE. (":" USED
INY ;2 FORCE A 3-BYTE ZERO-PAGE ADR.)
CPY #10 ;4 BYTES TO COPY (6 TO 9).
BNE MOVPTRS
* CHECK DRIVE STATUS.
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 2 LAST-USED DRV.
CMP (PTR2IOB),Y ;DRV# WANTED VS DRV# LAST USED.
BEQ SAMEDRV
STA (PTR2IOB),Y ;DESIGNATE DRV# WANTED AS LAST-
;USED DRV# FOR NEXT TIME AROUND.
PLP ;GET STATUS BACK OFF STK.
LDY #0 ;RESET STATUS (Z-FLAG OFF) TO
;SIGNAL THAT SPECIFIC DRV # WE
;WANT IN SPECIFIC SLOT WANTED WAS
;NOT ORIGINALLY SPINNING.
PHP ;PUSH UPDATED STATUS BACK ON STK.
SAMEDRV ROR ;PUT LOW BIT OF DRV WNTED IN (C).
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
;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.
PLP ;GET PREVIOUS TEST RESULT.
PHP ;PUT IT BACK ON STK 4 LATER USE.
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 POS'NING
* 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 THE
* STEPPER MOTOR.)
*
* (AMOUNT OF DELAY IS NOT CONSTANT
* CAUSE IT DEPENDS ON WHAT IS IN
* ACCUMULATOR & WE DON'T KNOW
* CAUSE WE WERE JUST ACCESSING
* HARDWARE.)
LDY #7
WAIT4MTR JSR DELAY ;STALL.
DEY
BNE WAIT4MTR ;GO STALL SOME MORE.
LDX SLOTPG5 ;RESTORE (X) = SLOT*16.
WASON LDY #4 ;GET TRK WANTED.
LDA (PTR2IOB),Y
JSR SEEKTRK ;GO MOVE ARM TO CORRECT TRK.
* CHECK TO SEE IF MOTOR WAS
* ORIGINALLY ON.
PLP ;GET EARLIER RESULT OF MOTOR TEST
BNE BEGINCMD ;BRANCH IF DRV WAS ORIGINALLY ON.
LDY MTRTIME+1 ;MOTOR WASN'T ORIGNALLY ON.
;HOWEVER, WE HAVE SINCE TURNED IT
;ON. NOW CHECK IF IT HAS BEEN ON
;LONG ENOUGH.
BPL BEGINCMD ;YES -NO NEED TO WAIT ANY LONGER.
* ALTHOUGH MOTOR IS TURNED ON, IT
* HASN'T BEEN ON LONG ENOUGH TO DO
* ACCURATE READING OF BYTES. THERE4
* DELAY UNTIL MOTOR ON TIME IS ONE
* SECOND (AT WHICH TIME MTRTIME
* COUNT IS 0). (PART OF TIME WAS
* TAKEN UP TO SEEK TRACK.)
TIME1 LDY #18
TIME2 DEY
BNE TIME2
INC MTRTIME
BNE TIME1
INC MTRTIME+1
BNE TIME1
*=================================
* MOTOR IS UP TO SPEED SO NOW
* PROCESS COMMAND (SEEK=00,
* READ=01, WRITE=02, FORMAT=04).
*---------------------------------
* USE THE FOLLOWING COUNTERS:
* READCNTR = ALLOW UP TO 48 TIMES
* TO FIND CORRECT ADR
* 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.
BEGINCMD LDY #12 ;GET CMD FROM IOB.
LDA (PTR2IOB),Y
BEQ WASEEK ;BRANCH IF CMD WAS "SEEK".
CMP #4 ;WAS CMD "FORMAT"?
BEQ FORMDSK ;BRANCH IF CMD WAS "FORMAT".
*---------------------------------
* COMMAND WAS READ OR WRITE
* (OPCODES $01 OR $02)
*---------------------------------
ROR ;(C)=1 IF READ (OPCODE %00000001)
;(C)=0 IF WRIT (OPCODE %00000010)
PHP ;SAVE (C) DENOTING CMD ON STK.
BCS RESETCNT ;READING - SO SKIP PRENIBBLING.
* COMMAND WAS WRITE
WASWRITE JSR PRENIBL ;CONVERT 256 MEMORY BYTES TO 342
;6-BIT NIBBLES NEEDED FOR WRITING.
* COMMON TO READ OR WRITE.
RESETCNT LDY #48 ;INIT COUNT TO READ ADR HEADER.
STY READCNTR
SETXSLT LDX SLOTPG5 ;SET (X)=SLOT*16.
JSR RDADDR ;GO READ ADDR HEADER TO FIND SEC
;THAT WE WANT TO READ OR WRITE.
BCC RDRIGHT ;ADDR READ WAS GOOD.
* BAD ADDRESS (OR DATA) READ.
REDUCERD DEC READCNTR ;REDUCE READ COUNT.
BPL SETXSLT ;TRY AGAIN.
* DO A RECALIBRATION CAUSE WE HAVE
* EXHAUSTED ALL ATTEMPTS TO GET A
* GOOD READ.
DORECALB LDA PRESTRK ;SAVE TRK WANTED ON STK.
PHA
LDA #96 ;PRETEND PRESENTLY ON TRK #96 SO
;WE FORCE HEAD AGAIN STOP.
;(REPEATEDLY BANGING HEAD AGAINST
;STOP = FAMILIAR DISK CLATTER.)
JSR SETTRK ;GO SELECT DRV & PUT TRK WANTED
;IN MEM LOCATION SPECIFIC 2 DRV.
DEC RECLBCNT ;REDUCE RECALIBRATION COUNTER.
BEQ DRVERR ;ERROR -EXHAUSTED RECALIBRATIONS.
LDA #4 ;INDICATE 4 CHANCES TO RESEEK TRK
STA RSEEKCNT ;BETWEEN RECALIBRATIONS.
LDA #0 ;SEEK TRACK 0.
JSR SEEKTRK ;GO MOVE ARM TO TRK 0.
PLA ;GET TRK WANTED FROM STK.
RESEEK JSR SEEKTRK ;NOW, MOVING OUT FROM TRK 0, TRY
;TO LOCATE TRK WANTED.
JMP RESETCNT ;GO BACK & TRY TO DO READ AGAIN.
* GOT A GOOD READ.
RDRIGHT LDY TRKDSK ;(Y) = TRK# FOUND IN HEADER.
CPY PRESTRK ;TRK FOUND = TRK WANTED?
BEQ RTTRK ;YES - SEEEKED TO CORRECT TRK.
* BAD SEEK (OR ELSE SOME KIND
* OF PROTECTION SCHEME) CAUSE
* TRK WANTED < > TRK FOUND.
LDA PRESTRK ;SAVE TRK WANTED ON STK.
PHA
TYA ;SET (A) =PRESENT TRK =TRK FOUND.
JSR SETTRK ;GO SELECT DRV & PUT TRK WANTED N
;MEMORY LOCATION SPECIFIC TO DRV.
PLA ;GET TRK WANTED BACK OFF STACK.
DEC RSEEKCNT ;ALLOW 4 ATTEMPTS TO FIND CORRECT
;TRK BETWEEN RECALIBRATIONS.
BNE RESEEK ;MORE ATTEMPTS LEFT TO FIND TRK.
BEQ DORECALB
*---------------------------------
* GOT A DRIVE ERROR.
*---------------------------------
DRVERR PLA
LDA #$40 ;ERROR CODE FOR BAD DRIVE.
TOERRWTS PLP
JMP RWTSERR
*---------------------------------
* RWTS COMMAND WAS SEEK (NULL).
*---------------------------------
WASEEK BEQ RWTSEXIT ;IF CMD WAS SEEK, THEN GO EXIT
;RWTS CAUSE JUST COMPLETED MOVE.
*---------------------------------
* RWTS COMMAND WAS FORMAT ($04).
*---------------------------------
FORMDSK JMP FORMAT ;GO DO THE FORMAT.
*---------------------------------
* FOUND CORRECT TRK FOR RWTS'S
* READ OR WRITE COMMANDS.
*---------------------------------
RTTRK LDY #3 ;GET VOL WANTED FROM IOB.
LDA (PTR2IOB),Y
PHA ;SAVE IT ON THE STACK.
LDA VOLDSK ;GET VOL FOUND AND SAV IT IN IOB.
LDY #14
STA (PTR2IOB),Y
PLA ;RETRIEVE VOL WANTED OFF STK.
BEQ CRCTVOL ;VOLUME 0 GOOD FOR ALL.
CMP VOLDSK ;VOL WANTED = VOL FOUND?
BEQ CRCTVOL ;YES - GOT CORRECT VOL#.
* GOT A VOLUME MISMATCH.
LDA #$20 ;SET CODE FOR VOL MISMATCH.
BNE TOERRWTS ;ALWAYS.
* FOUND CORRECT VOLUME SO NOW CHK
* IF THE SECTOR IS ALSO CORRECT.
CRCTVOL LDY #5 ;GET LOGICAL SECTOR # WANTED.
LDA (PTR2IOB),Y
TAY ;SET (Y) = LOGICAL SECTOR# WANTED.
LDA PHYSECTR,Y ;(A) = PHYSICAL SECTOR # WANTED.
CMP SECDSK ;PHYS SEC WANTED=PHYS SEC FOUND?
BNE REDUCERD ;NO - GO TRY AGAIN.
PLP ;GET TYPE OF OPERATION FROM STK:
; (C)=0=WRITE, (C)=1=READ.
BCC WRITE ;BRANCH IF RWTS OPCODE WAS WRITE.
* READ DATA SEC INTO RWTS'S BUFFERS.
JSR READATA ;GO READ A SECTOR.
PHP ;SAVE STATUS OF READ ON STACK JUST
;IN CASE WE NEED TO RE-READ.
BCS REDUCERD ;BAD READ - GO TRY AGAIN. LEAVE
;SET (C) ON STK 2 DENOTE READING.
;(WE PREVIOUSLY PULLED THE SAVED
;STATUS OFF THE STK. THERE4, WE
;BETTER PUT A SET (C) BACK ON STK
;CAUSE WE ARE READING AND WE ARE
;ABOUT 2 BRANCH BACK 2 A ROUTINE
;THAT EXPECTS THE READ (C=1) OR
;WRITE (C=0) FLAG ON THE STACK.
PLP ;GOOD READ -NOT BRANCHING BACK SO
;NO NEED TO PRESERVE FLAG ON STK.
* POSTNIBBLE DATA & SHUT DOWN.
LDX #0
STX PROSCRTH
JSR POSTNB16 ;CONVERT 6- & 2-ENCODED BYTES IN
;RWTS BUFS TO NORMAL MEMORY BYTES
;(USUALLY PLACED IN DOS DATA
;SECTOR BUFFER).
LDX SLOTPG5 ;SET (X) = SLOT*16 FROM PAGE 5.
*----------------------------------
* SIGNAL SUCCESS OR FAILURE
* AND THEN SHUT DOWN.
*----------------------------------
* SEVERAL REFERENCES ERRONEOUSLY
* STATE THAT THE RETURN CODE IS
* ZERO IF NO ERRORS OCCURRED.
* HOWEVER, A LONE SEEK OPERATION
* ALWAYS SETS THE RTN CODE TO ZERO.
* EVEN IF A READ OR WRITE OPERATION
* WAS SUCCESSFUL, THE IOB RTN CODE
* WILL ACQUIRE A RANDOM VALUE (AS
* A RESULT OF ACCESSING A HARDWARE
* SWITCH PRIOR TO ENTERING THIS
* ROUTINE). THERE4, THE RTN CODE
* IS ONLY RELEVANT IF AN ERROR IS
* DENOTED (CARRY SET).
RWTSEXIT CLC ;(C)=0, SIGNL SUCCESSFUL OPERAT'N
HEX 24 ;"BIT $38" 2 IGNORE "SEC" INSTRUC
RWTSERR SEC ;(C)=1, SIGNL UNSUCCESSFUL OPER'N
LDY #13 ;STORE RETURN CODE IN IOB.
STA (PTR2IOB),Y
LDA MTROFF,X ;TURN MOTOR OFF.
RTS
*---------------------------------
* WRITE SECTOR.
*---------------------------------
WRITE JSR WRITESEC ;WRITE SYNC GAP AFTR ADR EPILOGUE
;& THEN WRITE DATA PROLOGUE, DATA
;PROPER AND DATA EPILOGUE.
BCC RWTSEXIT ;GOOD WRITE - GO EXIT.
LDA #$10 ;WRITE PROTECT ERROR CODE.
BCS RWTSERR ;BAD WRITE - HANDLE THE ERROR.
*=================================
* DETERMINE DRIVE TYPE & MOVE
* DISK ARM TO DESIRED TRK.
*=================================
SEEKTRK PHA ;SAVE # OF TRK WANTED ON STK.
LDY #1 ;GET DRIVE TYPE (EVEN VAL=2PHASE,
LDA (PTR2DCT),Y ;ODD VAL=1PHASE) FROM DCT.
;(PS. THE "II" IN THE "DISK II"
;LOGO STAMPED ON APPLE'S DISK
;DRIVE DENOTES A 2-PHASE MOTOR.)
ROR ;PUT LOW BYTE OF DRV TYPE IN (C).
PLA ;GET TRK# WANTED BACK IN (A).
BCC SEEKIT ;NOT USING STANDARD DRIVE II,
;USING A ONE-PHASE DRIVE INSTEAD,
;THERE4 SKIP DOUBLING OF TRK# AND
;USE SEEKIT AS PART OF ROUTINE
;INSTEAD OF AS A SEPERATE SUBRTN.
* USING A TWO-PHASE DRIVE.
ASL ;2*TRK# WANTED=1/2TRACK# WANTED.
JSR SEEKIT ;MOVE THE DISK ARM 2 DESIRED TRK.
LSR PRESTRK ;CONVERT HALFTRACK VALUE BACK TO
RTS ;WHOLE TRACK VALUE.
*=====================================
* ROUTINE/SUBROUTINE TO MOVE DRIVE
* ARM TO A SPECIFIC TRK POS'N.
*=====================================
* USED AS A SUBROUTINE WHEN USING
* APPLE'S DISK DRIVE II. NOTE WHEN
* SEEKIT IS USED AS A SUBROUTINE,
* DESTRK, PRESTRK, TRK4DRV1, TRK4DR2,
* STPSDONE AND HOLDPRES ARE ALL
* EXPRESSED IN TERMS OF HALFTRACKS:
* DESTRK = DESTINATION HALF-TRACK POS'N.
* PRESTRK = PRESENT HALF-TRACK POS'N.
* HOLDPRES = PRESENT HALF-TRACK POS'N.
* TRK4DRV1 = BASE ADR (INDEXED BY SLOT*16)
* TO POINT TO THE ADR THAT
* CONTAINS THE LAST HALF-
* TRACK # THAT DRIVE1 WAS
* ALIGNED ONE.
* TRK4DRV2 = BASE ADR (INDEXED BY SLOT*16)
* TO POINT TO THE ADR THAT
* CONTAINS THE LAST HALF-
* TRACK # THAT DRIVE2 WAS
* ALIGNED ON.
* STPSDONE = NUMBER OF HALFTRACKS
* MOVED SO FAR.
* (NOTE: IF NOT USING A II-PHASE
* DRIVE, CHANGE ALL THE COMMENTS
* BELOW THAT REFER TO HALFTRACKS
* TO REFER TO FULLTRACKS INSTEAD.)
SEEKIT STA DESTRK ;(A) = HALFTRACK# WANTED.
JSR SLOTX2Y ;CONVERT (X)=SLOT*16-->(Y)=SLOT.
LDA TRK4DRV1,Y ;PRES HALFTRK # ASSOC WITH DRV1.
BIT DRVZPG ;CONTAINS: NEG=DRV1, POS=DRV2.
BMI SETPRSTK ;BRANCH IF USING DRIVE1.
LDA TRK4DRV2,Y ;USING DRIVE2 SO GET PRESENT
;HALFTRACK # ASSOC WITH DRIVE 2.
SETPRSTK STA PRESTRK ;SAVE PRESENT HALFTRK#.
* DESIGNATE HALFTRK WE ARE ABOUT
* TO SEEK AS PRESENT HALFTRK FOR
* NEXT TIME AROUND. (PUT HALFTRK
* INFO IN SLOT-DEPENDENT LOCATIONS.)
LDA DESTRK ;HALFTRK WANTED.
BIT DRVZPG ;CHK WHICH DRIVE WE'RE USING.
BMI DRV1USG ;BRANCH IF USING DRIVE 1.
STA TRK4DRV2,Y ;USING DRIVE2 -STORE HALFTRK INFO
;FOR NEXT TIME AROUND.
BPL DRV2USG ;ALWAYS.
DRV1USG STA TRK4DRV1,Y ;USING DRIVE1. STORE HALFTRK INFO
;FOR NEXT TIME AROUND.
DRV2USG JMP SEEKABS ;GO MOVE DRIVE ARM.
*===================================
* TRANSLATE (X)=SLOT*16 TO (Y)=SLOT.
*===================================
SLOTX2Y TXA ;GET SLOT*16 FROM (X).
LSR ;DIVIDE IT BY 16.
LSR
LSR
LSR
TAY ;PUT SLOT# IN (Y).
RTS
*=================================
* GO SELECT DRIVE AND PUT TRACK #
* WANTED IN MEMORY LOCATION ASSOC
* WITH THE # OF THE DRIVE WE'RE
* USING.
*=================================
SETTRK PHA ;SAVE PRESENT TRK # ON STK.
LDY #2 ;GET DRV # WANTED FROM IOB.
LDA (PTR2IOB),Y
ROR ;CONDITION CARRY:
; (C)=0=DRV1, (C)=1=DRV2.
ROR DRVZPG ;CONDITION ZERO-PAGE LOCATION:
; NEG=DRV1, POS=DRV2.
JSR SLOTX2Y ;USE (X)=SLOT*16 TO GET (Y)=SLOT.
PLA ;GET TRK # WANTED OFF STK.
ASL ;TIMES TWO FOR 1/2TRACK # WANTED.
BIT DRVZPG ;CHK WHICH DRIVE TO USE.
BMI STORDRV1 ;BRANCH IF USING DRIVE 1.
STA TRK4DRV2,Y ;SAV HALFTRK # WANTED FOR DRIVE2.
BPL RTNSETRK ;ALWAYS.
STORDRV1 STA TRK4DRV1,Y ;SAVE HALFTRK # WANTED 4 DRIVE1.
RTNSETRK RTS
*=================================
* RWTS'S FORMAT COMMAND.
*=================================
* INITIALIZE ZERO-PAGE LOCATIONS.
FORMAT LDY #3 ;GET VOL FRM IOB, STORE IN Z-PAGE.
LDA (PTR2IOB),Y
STA FRMTVOL
LDA #$AA ;STORE "AA" AS CONSTANT IN Z-PAGE.
STA HOLDAA
LDY #$56 ;INITIALIZE INDEX TO BUFFER.
LDA #0 ;INITIALIZE TRK COUNTER.
STA FRMTKCTR ;NOTE: ALWAYS BEGIN FORMATTING
;WITH TRACK $00.
* ZERO OUT THE RWTS BUFFERS.
* (NOTE: WHEN FORMATTING, THESE
* "$00" BUFFER BYTES WILL LATER BE
* TRANSLATED AND WRITTEN TO THE
* DISK AS "$96" DISK BYTES.)
* ZERO OUT RWTS BUFFER THAT NORMALLY
* CONTAINS 2-ENCODED NIBBLES.
* (RWTSBUF2, $BC00 <--- $BC55.)
ZBUF2 STA RWTSBUF1+$FF,Y ;($BC55 --> $BC00.)
DEY
BNE ZBUF2
* ZERO OUT RWTS BUFFER THAT NORMALLY
* CONTAINS 6-ENCODED NIBBLES.
* (RWTSBUF1, $BB00 ---> $BBFF.)
ZBUF1 STA RWTSBUF1,Y
DEY
BNE ZBUF1
* PREPARE TO DO A RECALIBRATION.
LDA #80 ;PRETEND WE'RE ON TRK #80.
JSR SETTRK ;GO SELECT DRV & PUT HALFTRACK #
;WANTED IN MEMORY LOCATION ASSOC
;WITH THE # OF DRV BEING USED.
LDA #40 ;SET UP FOR 40 SYNCS BTWN SECS
STA SYNCNTR ;ON TRK0. NOTE THAT THIS # WILL
;LATER BE REDUCED AS WE WRITE
;SUBSEQUENT TRKS.(HIGHER NUMBERED
;TRKS ARE CLOSER TO THE CENTER OF
;THE DSK & THERE4 ARE REPRESENTED
;BY SMALLER CIRCLES. WE CAN CROWD
;ALL THE SECS INTO A SMALLER
;CIRCUMFERENCE BY REDUCING THE #
;OF SYNC BYTES BETWEEN SECS.
* FORMAT THE NEXT TRACK.
FRMNXTRK LDA FRMTKCTR ;USE TRK COUNTER AS TRK TO SEEK.
JSR SEEKTRK ;POS'N ARM OVER CORRECT TRK.
* GO FORMAT A SPECIFIC TRACK.
JSR FORMATRK ;FORMAT A TRACK.
LDA #8 ;SET (A) AS DEFAULT VALUE IN CASE
;COULDN'T FORMAT. NOTE THAT ANY
;TYPE OF ERROR ENCOUNTERED WHEN
;FORMATTING YEILDS AN I/O-ERROR
;MESSAGE.
BCS ERRFRMT ;BRANCH IF COULDN'T FORMAT.
* DO A READ CHK OF TRK JUST FORMATTED.
* (EVENTHOUGH TRACK VERIFIED, READ
* IT AGAIN UNTIL LOCATE TRK0.
* (PRESUMABLY, THIS (PARTIALLY)
* DOUBLE CHECKS VERIFICATION AND
* KEEPS SECTORS IN DIFFERENT TRACKS
* SOMEWHAT ADJACENT?)
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.
JSR RDADDR ;GO READ ADDR HEADER TO FIND SEC
;THAT WE WANT TO READ OR WRITE.
BCS RDAGAIN ;BAD READ - TRY AGAIN.
LDA SECDSK ;WAS IT SECTOR 0?
BNE RDAGAIN ;NO - TRY AGAIN.
JSR READATA ;LAST CHANCE TO READ DATA.
BCS RDAGAIN ;LAST CHANCE BOMBED OUT!!!
INC FRMTKCTR ;KICK UP TRK COUNTER.
LDA FRMTKCTR ;SET (A) FOR NEXT TRK COUNT.
CMP #$23 ;DONE ALL TRACKS YET (#0 TO #34)?
BCC FRMNXTRK ;NO - GO FORMAT THE NEXT TRACK.
CLC ;SIGNAL FINISHED ALL TRACKS.
BCC DONEFRMT ;ALWAYS - ONLY GOOD EXIT.
* NOTE: NO MATTER WHAT KIND OF ERROR
* WE MIGHT HAVE ENCOUNTERED WHEN
* FORMATTING, THE IOB ERROR CODE IS
* SET TO $08. THIS IS LATER TRANSLATED
* TO AN FM ERROR CODE (ALSO $08) WHICH
* DOS DISPLAYS AS AN I/O ERROR MSG.
* (THIS IS WHY TRYING TO FORMAT A
* WRITE-PROTECTED DISK RESULTS IN AN
* I/O ERROR MSG INSTEAD OF A DISK-
* WRITE-PROTECTED MSG.)
* IF NO ERROR OCCURRED, THE IOB RETURN
* CODE WILL BE SET TO SOME RANDOM
* NUMBER (FROM REFERENCING A HARD-
* WARE SWITCH ADDRESS).
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 THE MOTOR OFF, XIT WITH (C)
RTS ;DENOTING SUCCESS STATUS.
*------------------------------------
* SUBROUTINE 2 FORMAT A SPECIFIC TRK.
*------------------------------------
* SECTORS ARE WRITTEN IN ASCENDING
* ORDER FROM SEC $00 TO SEC $0F.
* (NOTE THAT THE FORMAT ROUTINE ONLY
* DEALS WITH PHYSICAL SECTOR NUMBERS.)
FORMATRK LDA #0 ;ALWAYS START WITH SEC $00.
STA FRMTSEC
LDY #128 ;USE 128 SYNC BYTS BEFORE SEC$00.
;NOTE: THIS GAP WILL BE PARTIALLY
;OVERWRITTEN BY SEC $0F.
BNE DOADDR ;ALWAYS.
FRMTASEC LDY SYNCNTR ;SET (Y)= # OF 40-CYCLE SELF-SYNC
;BYTES TO BE WRITTEN BTWN SECS.
;(THIS # VARIES DEPENDING ON THE
;SPEED OF THE SPECIFIC DRV BEING
;USED & THE # OF THE TRK BEING
;WRITTEN.)
DOADDR JSR WRITADR ;WRITE SYNC BYTES & ADDR HEADER.
BCS VRFYRTN ;ERROR -DISK WAS WRITE PROTECTED.
JSR WRITESEC ;WRITE SYNC GAP BTWN ADDR & DATA
;FIELDS, WRT DATA & WRITE A SYNC
;BYTE AFTER DATA EPILOGUE.
BCS VRFYRTN ;IRRELEVANT - NEVER TAKEN BECAUSE
;WE ALREADY CHECKED THE WRITE-
;PROTECT SWTCH WHEN WE WROTE ADR.
INC FRMTSEC ;INCREASE SEC #.
LDA FRMTSEC
CMP #$10 ;DONE ALL 16 SECS YET?
BCC FRMTASEC ;NO - GO DO SOME MORE.
*......................................
* VERIFY A SINGLE TRACK.
*......................................
* NOTE WE JUST FINISHED FORMATTING
* SEC $0F. BECAUSE SEC $0F SHOULDN'T
* OVERWRITE TOO MUCH OF OF THE SYNC GAP
* (ORIGINALLY 128 SYNC LONG) THAT WAS
* 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.
* INTIALIZE COUNTERS.
LDY #$0F ;SET COUNTER 4 # OF SECS VERIFIED
STY FRMTSEC
LDA #48 ;SET COUNTER FOR # OF ATTEMPTS.
STA READCNTR
* FILL SECTOR MAP WITH POSITIVE NUMBERS.
FILSECMP STA SECFLGS,Y
DEY
BPL FILSECMP
* DELAY TO LET SOME SYNCS PASS BY.
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)
BNE BYPSYNCS ;(3 CYC ON BRNCH, 2 ON FALL THRU)
* READ ADDRESS OF FIRST SEC ENCOUNTERED.
* (THIS BETTER BE SEC $00!!!! IF IT
* ISN'T, OUR DRIVE IS TOO FAST & WE
* WILL EVENTUALLY HAVE TO REFORMAT
* THE TRACK.)
JSR RDADDR ;READ ADR OF 1RST SEC ENCOUNTERED
BCS REREADDR ;BAD READ, TRY AGAIN.
LDA SECDSK ;WAS SEC READ = SEC00?
BEQ RDNXTDAT ;YES - GO READ NEXT DATA SEC.
* DIDN'T FIND SECTOR $00 WHEN EXPECTED!!!!
* DRIVE MUST BE FASTER THAN ANTICIPATED
* CAUSE SEC $0F OVERLAID TOO MUCH OF
* THE LONG SYNC GAP (GAP1) THAT WAS
* ORIGINALLY WRITTEN BEFORE SEC $00.
* WE WILL EVENTUALLY HAVE TO REFORMAT
* THIS TRK USING 128 SELF-SYNCS BEFORE
* SEC $00 (GAP1) AND LESS SYNC BYTES
* BETWEEN OTHER SECS (GAP3). THIS
* WILL INSURE THAT LESS GAP-1 SYNCS
* WILL BE OVERWRITTEN BY SEC $OF.
* NOTE THAT DEPENDING ON JUST HOW
* MUCH TOO FAST THE DRIVE IS, WE MAY
* HAVE TO REFORMAT THIS TRK SEVERAL
* TIMES BEFORE WE GET IT RIGHT. EACH
* TIME WE REFORMAT, WE REDUCE THE #
* OF GAP-3 SYNCS. IF THE SYNC COUNTER
* IS > = 16, WE WRITE 2 LESS SYNCS.
* IF THE COUNTER IS < 16, WE ONLY REDUCE
* GAP-3 BY ONE SYNC. IN ORDER TO GIVE
* THE MACHINE TIME TO DECODE INFO, WE
* WON'T ALLOW A GAP LESS THAN 5 SYNCS
* LONG. (NOTE THAT WE WON'T REFORMAT
* THE TRACK UNTIL WE FIND THE ADR HEADER
* FOR SEC $0F. THIS PRESUMABLY KEEPS
* LIKE-NUMBERED SECS IN ADJACENT TRKS
* IN SOME SEMBLANCE OF ORDER.)
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 AT
RTS ;LEAST 5 SYNCS. DRIVE IS SO FAST
* === ;THAT IT IS USELESS. WE CAN'T
;EVEN COMPENSATE 4 IT BY REDUCING
;THE NUMBER OF GAP-3 SYNCS.
* READ THE SEC ADDR & DATA PROPER.
RDNXTADR JSR RDADDR ;READ THE ADDR HEADER.
BCS BADREAD ;BRANCH IF BAD ADDRESS READ.
RDNXTDAT JSR READATA ;READ THE DATA PROPER.
BCC CKSECMAP ;READ WAS GOOD -SO GO CHK IF THIS
;SEC HAS ALREADY BEEN READ.
BADREAD DEC READCNTR ;EITHER GOT A BAD READ OR ELSE
;WE ALREADY VERIFIED THIS SEC.
;REDUCE THE # OF CHANCES LEFT.
BNE RDNXTADR ;MORE CHANCES LEFT -GO TRY AGAIN.
* DOING A RE-READ. WILL DEFINITELY
* HAVE TO REFORMAT.
REREADDR JSR RDADDR ;READ AN ADDR HEADER.
BCS NOTLAST ;GOT A BAD READ.
* WE WILL REFORMAT BUT WE DON'T WANT
* TO DO SO UNTIL WE READ SEC $0F.
* HAVE WE FOUND SEC $0F YET?
LDA SECDSK ;GET PHYS # OF SEC JUST READ.
CMP #$0F ;WAS IT SEC 15?
BNE NOTLAST ;NO, SO GO LOOK SOME MORE.
JSR READATA ;YES - READ THE DATA IN SEC $0F.
BCC FORMATRK ;GOOD READ ON SEC15 SO NOW TIMING
;IS RIGHT TO GO REFORMAT THIS TRK
NOTLAST DEC READCNTR ;BAD READ, CK IF MORE CHANCES LFT
BNE REREADDR ;YES - GO TRY AGAIN.
SEC ;EXHAUSTED ALL CHANCES, SO SET
VRFYRTN RTS ;(C) AS ERROR FLAG & EXIT.
* ===
* CHECK IF THIS SEC WAS PREVIOUSLY
* VERIFIED. IF NOT, UPDATE SECTOR
* VERIFICATION MAP. (IF TIMING IS
* RIGHT, SHOULD NEVER ENCOUNTER AN
* ALREADY VERIFIED SEC BEFORE FRMTSEC
* DECREMENTS FROM $0F DOWN TO $FF.)
CKSECMAP LDY SECDSK ;USE # OF SEC FOUND AS INDEX TO
;THE VERIFICATION MAP.
LDA SECFLGS,Y ;GET MAP BYT (NEG=PREV VERIFIED).
BMI BADREAD ;OH!OH! ALREADY VERIFIED THIS ONE
LDA #$FF ;SET BYTE IN MAP TO SIGNAL THAT
STA SECFLGS,Y ;THIS SEC WAS JUST VERIFIED.
DEC FRMTSEC ;ANY SECS LEFT TO VERIFY?
BPL RDNXTADR ;YES - GO DO SOME MORE.
* ALL SECS VERIFIED, SO CHECK
* IF WE JUST DID TRACK $00.
LDA FRMTKCTR ;WAS TRK JUST FORMATTED =TRK $00?
BNE NOTRK0 ;NO - SO EXIT CLEANLY.
* JUST FORMATTED & VERIFIED TRK $00.
* TRK $00 IS THE OUTSIDE TRK AND THERE4
* HAS THE LARGEST LENGTH IN WHICH TO
* WRITE BYTES. BECAUSE SUBSEQUENT
* TRKS HAVE A SMALLER CIRCUMFERENCE,
* WE MUST REDUCE THE NUMBER OF SYNCS
* TO WRITE BETWEEN SECS (GAP3) SO WE
* CAN GET ALL THE NEEDED INFO INTO
* A SMALLER SPACE.
LDA SYNCNTR ;CHECK SYNC COUNT.
CMP #16 ;LESS THAN 16 SYNCS?
BCC VRFYRTN ;YES - EXIT CLEANLY.
;DON'T WANT TO START OFF WITH A
;SMALLER GAP SO SKIP CODE BELOW.
* REDUCE THE SIZE OF GAP3.
DEC SYNCNTR ;GAP > = 16 SYNCS LONG, SO CAN
DEC SYNCNTR ;AFFORD 2 REDUCE IT BY 2 IN ORDER
NOTRK0 CLC ;TO ACCOMMODATE A TIGHTER TRACK.
RTS ;EXIT CLENALY.
*=================================
* FLAGS FOR SECTOR VERIFICATION.
* ($BFA8 - $BFB7)
* - NEG VAL = SECTOR VERIFIED.
* - TABLE IS INDEXED BY (Y),
* WHERE (Y) = SECTOR NUMBER.
*=================================
SECFLGS HEX FFFFFFFFFFFFFFFF ;SECS $00 TO $07.
HEX FFFFFFFFFFFFFFFF ;SECS $08 TO $0F.
*=================================
* PHYSICAL SECTOR NUMBERS
* ($BFB8 - $BFC7)
* - LISTED IN LOGICAL ORDER.
*=================================
;CORRESPONDING LOGICAL SECTOR#.
PHYSECTR HEX 00 ; 00
HEX 0D ; 01
HEX 0B ; 02
HEX 09 ; 03
HEX 07 ; 04
HEX 05 ; 05
HEX 03 ; 06
HEX 01 ; 07
HEX 0E ; 08
HEX 0C ; 09
HEX 0A ; 0A
HEX 08 ; 0B
HEX 06 ; 0C
HEX 04 ; 0D
HEX 02 ; 0E
HEX 0F ; 0F
*=================================
* CLOBBER THE LANGUAGE CARD.
* ($BFD9 - $BFDB)
* - PATCH CALLED BY BOOT2.
*=================================
CLOBCARD JSR SETVID ;SIMULATE A "PR#0" STATEMENT.
LDA $C081 ;WRITE ENABLE RAM CARD.
LDA $C081 ;(READ MOTHER/WRITE CARD BANK2.)
LDA #0 ;SET LANGUAGE IDENTIFYING BYTE ON
STA BASICCLD ;CARD TO $00 SO IF CARD IS TESTED
;(DURING AN "FP" CMD), THE
;MACHINE WILL BE FORCED TO USE
;MOTHERBOARD VERSION OF FP.
JSR CONTCLOB ;NOW CLOBBER THE 80-COLUMN CARD.
JMP BK2BOOT2 ;RTN TO ORIGINAL PART OF BOOT2.
*===================================
* PATCH TO ZERO ADDED STORAGE BYTES.
* ($BFDC - $BFE5)
*===================================
ZEROPTCH STA TEMPBYT
STA BYTPRSD
STA BYTPRSD+1
RTS
*=================================
* PATCH TO SET CONDITION 0 AND
* CLEAR THE RUN INTERRUPT FLAG.
* ($BFE6 - $BFEC)
*=================================
RESTATIN JSR RESTAT0 ;ZERO OUT CONDNFLG & OPUTCOND.
STY RUNTRUPT ;CLR THE RUN INTERRUPT FLAG.
RTS
*=================================
* DISK-FULL ERROR PATCH.
* ($BFED - $BFFF)
*=================================
FULLPTCH JSR CPYFMWA ;COPY FM WRK AREA--->FM WRK BUF.
LDX STKSAV ;RESTORE STACK POINTER.
TXS
JSR CLOSEALL ;CLOSE ALL FILES.
TSX
STX STKSAV ;SAVE STACK POINTER.
LDA #9 ;EXIT WITH DISK-FULL ERROR CODE.
JMP BADFMXIT
**********************************
* END OF DOS ($BFFF) *
**********************************


Binary file not shown.

View File

@@ -0,0 +1,268 @@
**********************************
* *
* ADDRS USED IN THE FORMATTED *
* DIS'MBLIES BUT NOT REFERENCED *
* IN THE LINEAR DIS'MBLIES. *
* (THESE ADRS ARE INCLUDED TO *
* MAKE THE SYMBOL TBLS APPLICABLE*
* TO BOTH DIS'MBLIES.) *
* *
**********************************
*--------------------------------*
* ZERO-PAGE LOCATIONS *
*--------------------------------*
LOC0 = $00 ;REFERENCE ADR USD BY MONITOR ROM
;ROUTINES THAT SIMULATE IN# & PR#
;STATEMENTS.
LOC1 = $01 ;AS ABOVE.
GOWARM = LOC0 ;A JMP INSTRUC (3 BYTES, $00-$02)
;TO BASIC'S WARMSTART (RESTART,
;$D43C) ROUTINE. HOWEVER, WHEN
;COLDSTARTING, IS TEMPORARILY SET
;TO JUMP INTO BASIC'S COLDSTART
;AT BSCOLDST ($F128).
GOSTROUT = $03 ;A JMP INSTRUC (3 BYTES, $03-$05)
;TO THE BASIC ROUTINE THAT PRINTS
;THE STRING IN MEMORY POINTED TO
;BY (A) & (Y) REGS (IN LOW/HI
;FORMAT). HOWEVER, WHEN COLD-
;STARTING, IS TEMPORARILY SET TO
;JMP IN2 BASIC'S COLSTART ROUTINE
;AT BSCOLDST ($F128).
USR = $0A ;JUMP INSTRUC (3 BYTES, $0A-$0C)
;TO USR ROUTINE. HOWEVER, WHEN
;COLDSTARTING, IS TEMPORARILY
;PTING AT ILLEGAL-QUANTITY ROUT'N
SUBFLG = $14 ;SUBSCRIPT FLAG:
;$00 = SUBSCRIPT ALLOWED.
;$80 = NO SUBSCRIPTS.
WNDWDTH = $21 ;WIDTH OF TEXT SCREEN WINDOW.
INVFLG = $32 ;INVERSE FLAG MASK: NORMAL = $FF,
;INVERSE = $3F & FLASHING = $7F.
;HACKER'S OFTEN ZAP THIS BYTE TO
;FILTER OUTPUT AS PART OF A
;PROTECTION SCHEME (INVIS = $80).
BT0SCRTH = $3C ;MAIN SCRATCH REG USED BY BOOT0.
A2L = $3E ;MULTIPURPOSE REG & PTR ($3E,$3F)
BOOTEMP = $40 ;TRK # READ OFF DSK WHEN BOOTING.
BOOTRK = $41 ;TRK # WANTED WHEN READING IN DOS
;DURING THE BOOT PROCESS.
TEMPPT = $52 ;PREVIOUS TEMP STRING DESCRIPTOR.
LASTPT = $53 ;PREVIOUS TEMP STRING POINTER.
TEMPST = $55 ;PREVIOUS STRING POINTER USED IN
;GARBAGE COLLECTION ROUTINES.
INDEX = $5E ;TEMP STK PTR FOR MOVING STRINGS.
ARYTAB = $6B ;PTR ($6B,$6C) TO START OF THE
;ARRAY VARIABLES.
STREND = $6D ;PTR ($6D,$6E) TO START OF FREE
;SPACE. (1 BYTE BEYOND THE END OF
;THE ARRAY VARIABLES.)
OLDTEXT = $79 ;PTR ($79,$7A) TO NEXT STATEMENT
;TO BE EXECUTED.
DATPTR = $7D ;PTR ($7D,$7E) TO NEXT BYTE TO BE
;USED FOR A DATA STATEMENT.
DSCLEN = $8F ;TEMP BYTE USD 4 GARBAGE COLLECT.
JMPADRS = $90 ;JMP INTRUC ($90-$92) TO VARIABLE
;ADDR.
TEMPRY = $A4 ;TEMP BYTE USED IN FLOATING POINT
;MATH ROUTINES.
CHRGET = $B1 ;GET BYTE OF TEXT FROM TXTPTR IN
;(A), INCREMENT TXTPTR AND EXIT
;WITH: (A) = ORIGINAL CHAR.
; (Z) = 0 IF (A) = ":" OR $00
; = 1 IF (A) = '0' TO '9'
CHRGOT = $B7 ;AS ABOVE - BUT DON'T INC TXTPTR.
TXTPTR = $B8 ;PTR ($B8,$B9) TO NEXT BYTE OF
;PRGM TEXT.
CHRGTRTN = $C8 ;"RTS" AT END OF CHRGET/CHRGOT.
SPEEDFLG = $F1 ;# USED TO CTRL DELAY ($00-$FF).
TRCFLG = $F2 ;TRACE FLAG.
FLSHMSK = $F3 ;MASK FOR FLASHING OUTPUT.
;($40 FOR FLASH, ELSE $00).
*--------------------------------*
* PAGES ONE TO EIGHT *
*--------------------------------*
STACK = $100 ;TOP OF THE STACK.
BUF300 = $300 ;PAGE 3 - USED BY BOOT AS BUF TO
;STORE 2- & 6-ENCODED NIBBLES.
BTNIBL = $36C ;BOOT NIBBLE TABLE - USED TO
;TRANSLATE DISK BYTES TO ENCODED
;MEMORY BYTES.
SEC2RD08 = $800 ;DEFINES # OF SECS TO BE READ IN
;BY BOOT0.
BT1EXC08 = $801 ;START OF BOOT1. BOOT0 JMPS TO
;THIS LOCATION.
SKPREL08 = $81F ;TARGET LABEL FOR BRANCH WHEN
;BOOT1 IS EXECUTING IN PAGE 8.
;- DETERMINE # OF SECS LFT 2 READ
; IN, PHYS SEC # & TARGET ADR.
PRP4B208 = $839 ;TARGET LABEL FOR BRANCH WHEN
;BOOT1 IS EXECUTING IN PAGE 8.
;- PREPARE FOR BOOT2.
*--------------------------------*
* DISK CONTROLLER CARD ADRS *
*--------------------------------*
* NOTE: THE DISK CONTROLLER ROMS
* ARE RELOCATABLE TO ANY PAGE
* BOUNDARY. THE ACTUAL ADRS USED
* ARE DEPENDENT UPON WHICH SLOT
* (1 TO 7) HOUSES THE CONTROLLER
* CARD. WHEREAS THESE SLOTS ARE
* REPRESENTED BY PAGES $C1 TO $C7,
* THE HI BYTE OF THE FOLLOWING
* ADRS CAN BE CHANGED TO $CS WHERE
* S=SLOT #. THE SAMPLE ADRS GIVEN
* BELOW REFER TO A CARD IN SLOT6
* (PAGE $C6). THE FUNCTIONS OF
* EACH OF THE FOLLOWING ROUTINES
* IS DESCRIBED IN THE FORMATTED
* DISASEMBLY TITLED "THE BOOT PROCESS".
BUILDTBL = $C606
TESTCARY = $C614
GETNEWX = $C61E
MAGNTOFF = $C63D
PRSRVFLG = $C65D
STARTSEQ = $C65E
BTRYD5 = $C663
BTRYAA = $C667
BTRY96 = $C671
BTRYAD = $C67D
RDVLTKSC = $C683
MOREBYTS = $C685
BTRDODD = $C687
BTRDEVEN = $C68F
BTRDATA = $C6A6
KEEPCNT1 = $C6A8
RDDSK1 = $C6AA
KEEPCNT2 = $C6BA
RDDSK2 = $C6BC
RDCK = $C6CB
TSTREAD = $C6D3
SETX56 = $C6D7
DOWNX = $C6D9
*--------------------------------*
* APPLESOFT ADDRESSES *
*--------------------------------*
* A BRIEF DESCRIPTION OF THE
* FUNCTIONS OF THESE ROUTINES ARE
* GIVEN BELOW. NOTE THAT SOME OF
* THESE ROUTINES MAY BE INTERCEPTED
* BY DOS. (SEE FORMATTED DIS'MBLIES
* FOR DETAILS.)
ESTPTRS = $D4F5 ;RECALC LINK PTRS IN APPLESOFT
;PRGM IN CASE PRGM WAS NOT LOADED
;INTO THE SPACE AT WHICH IT WAS
;ORIGINALLY WRITTEN.
LOCEOP = $D4FE ;FIND END OF APPLESOFT PRGM.
STARTNXT = $D50F ;PUT NEW LINK IN FP PRGM LINE.
LOCEOL = $D511 ;FIND END OF APPLESOFT PRGM LINE.
INLIN = $D52C ;INPUT LINE OF TEXT IN2 INPUT BUF
;(WITHOUT PROMPT).
INLINPL2 = $D52E ;AS ABOVE, BUT USE VAL IN (X) AS
;PROMPT.
TERMIN8 = $D539 ;PUT AN END-OF-LINE MARKER (EOL,
;$00) IN INPUT BUFFER.
CNVRTPOS = $D541 ;CONVERT INPUT LINE TO POS ASCII.
NEG8NPUT = $D54C ;PREPARE TO INITIALIZE THE TEXT
;PTR. (SET A=0, Y=01, X=FF.)
CLEAR = $D66A ;SIMULATE A CLEAR STATEMENT.
CLEARC = $D66C ;CLEAR VARIABLES & TEXT.
STKINI = $D683 ;REINTIALIZE STK POINTER WHILE
;PRESERVING RETURN ADDRESS.
CLRTS = $D696 ;"RTS" AT END OF STKINI ROUTINE.
SETXTPT = $D697 ;SET TEXT PTR TO BEGINNING OF THE
;APPLESOFT PRGM.
RESTORE = $D849 ;SIMULATE A RESTORE STATEMENT.
SETDA = $D853 ;RESET PTR 2 DATA STATEMENT BYTE.
CRDO = $DAFB ;PRINT A <CR>.
STRPRT = $DB3D ;PRT STRING WHICH HAS DESCRIPTOR
;POINTED TO BY $A0,$A1.
OUTQUES = $BD5A ;PRINT A "?".
OUTDO = $DB5C ;PRINT CONTENTS OF (A) AS CHAR.
GODOPUT = $BD64 ;PRINT (A) VIA COUT.
INPUT = $DBB2 ;PROCESS AN INPUT STATEMENT.
NOPTNSTR = $DBC4 ;PROCESS AN INPUT STATEMENT WITH
;NO OPTIONAL STRING PROMPT.
CKDIFRD = $DBC7 ;BYPASS PRINTING "?" WHEN USING
;ALTERNATE STRING PROMPT INSTEAD.
STRTXT = $DE81 ;PRINT THE STRING.
SYNCHR = $DEC0 ;CHK BYTE POINTED TO BY TXTPTR TO
;SEE IF IT MATCHES (A). IF NOT,
;EXIT WITH SYNTAX ERROR.
IQERR = $E199 ;ILLEGAL QUANTITY ERROR.
WASDEF = $E2AC ;"RTS" ENCOUNTERED IF USING
;DEFERRED MODE WHEN PROCESSING AN
;INPUT STATEMENT.
ERRDIR = $E306 ;CHK IF IN DEFERRED OR IMMEDIATE
;MODE WHEN PROCESSING AN INPUT
;STATEMENT.
BSCOLDST = $F128 ;BEGIN BASIC'S COLDSTART SEQUENCE
MV2ZPG = $F152 ;COPY IMAGE OF CHRGET ROUTINE AND
;RANDOM # SEED TO PAGE ZERO. (BUG
;IN ROUTINE BECAUSE IT DOESN'T
;TRANSFER ALL OF RANDOM # SEED,)
NORMAL = $F273 ;SET NORMAL MODE.
INVERSE = $F277 ;SET INVERSE MODE.
NORMINV = $F279 ;SET INVERSE OR NORMAL MODE.
SETINV = $F27B ;STORE MASK 4 INVERSE IN INVFLG.
*--------------------------------*
* MONITOR ROM ROUTINES *
*--------------------------------*
* A BRIEF DESCRIPTION OF THE
* FUNCTIONS OF THESE ROUTINES ARE
* GIVEN BELOW. NOTE THAT SOME OF
* THESE ROUTINES MAY BE INTECEPTED
* BY DOS. (SEE FORMATTED DIS'MBLIES
* FOR DETAILS.)
CLREOL = $FC9C ;CLR LINE FRM CURRENT CURSOR POSN
;(BASL),(CH) 2 RIGHT EDGE OF WNDW
CLEOLZ = $FC9E ;CLR LINE FRM CURRENT CURSOR POSN
;(BASL),Y 2 RIGHT EDGE OF WINDOW.
CLEOL2 = $FCA0 ;PUT CHAR IN (A) FROM (BASL),Y TO
;RIGHT EDGE OF WINDOW.
WAIT = $FCA8 ;MONITOR ROM'S MAIN DELAY ROUT'N.
;DEALY Z # OF CYCLES BASED ON THE
;FORMULA:Z=((5*A^2)+(27*A)+26))/2
;WHERE A = VALUE IN ACCUMULATOR.
WAIT2 = $FCA9 ;TARGET 4 BRANCH IN WAIT ROUTINE.
WAIT3 = $FCAA ;TARGET 4 BRANCH IN WAIT ROUTINE.
ESC = $FD2F ;HANDLE AN <ESC> KEY INPUT.
RDCHAR = $FD35 ;PUT INPUT CHAR IN (A).
NOTCR = $FD3D ;HNDL INPUT CHAR OTHER THAN <CR>.
NOTCR1 = $FD5F ;HNDL INPUT CHAR OTHER THAN <CR>,
;<BKSPC> OR <CANCEL>.
CANCEL = $FD62 ;CANCEL THE INPUT LINE.
GETLNZ = $FD67 ;PRINT A <CR>, PROMPT & THEN READ
;A LINE OF INPUT.
BCKSPC = $FD71 ;HANDLE A BACKSPACE ("<-").
NXTCHAR = $FD75 ;READ THE NEXT CHAR.
CAPTST = $FD7E ;MAKE CHR UPPERCASE IF NECESSARY.
ADDINP = $FD84 ;PUT (A) IN INPUT BUF.
CROUT = $FD8E ;PRINT <CR> THROUGH COUT.
INPRT = $FE8D ;SELECT INPUT PORT # (A).
OUTPRT = $FE97 ;SELECT OUTPOUT PORT # (A).
IOPRT = $FE9B ;TEST IF I/O PORT # IS ZERO.
IOPRT1 = $FEA7 ;SET ZERO-PAGE POINTER (X,X+1) TO
;POINT AT $FD--.
IOPRT2 = $FEA9 ;SET ZERO-PAGE POINTER (X,X+1) TO
;POINT AT $(A)(Y).
BELL = $FF3A ;RING WARNING BELL WHEN INPUT BUF
;IS JUST ABOUT FULL.
-

View File

@@ -0,0 +1,556 @@
******************************************************************
* *
* VERIFY, LOCK and UNLOCK Command Handlers *
* *
*----------------------------------------------------------------*
* *
* The LOCK command protects a file from being accidentally *
* deleted or overwritten. This protection is removed by the *
* UNLOCK command. The VERIFY command checks that the data *
* associated with a particular file is encoded on the disk *
* correctly. *
* All three commands require a file name and can be issued *
* with the optional volume, drive and slot parameters. Their *
* execution patterns are also very similar. After loading the *
* accumulator with the appropriate opcode, part of the common *
* file manager command handler code is called to: *
* 1) close the file if it is already open. *
* 2) reassign a DOS buffer to the file to be *
* verified, locked or unlocked. *
* 3) call the file manager to do the function. *
* 4) close the file. *
* The lock/unlock FUNCTIONS have almost identical function *
* handlers. After setting LOKUNLOK ($B39E) to lock ($80) or *
* unlock ($00) the file, the COMNOPEN routine ($AB28) is called *
* to search the directory sector for the file description entry *
* corresponding to the named file. Failure to find the wanted *
* file results in a file-not-found error message. If the named *
* file is located, its file type code is read from the *
* description entry. After the hi bit of the code is dropped, *
* it is merged with the LOKUNLOK mask ($B39E) and stored back *
* in the file description entry. The file is then locked or *
* unlocked depending on whether the hi bit of the file type code *
* is set or clear. (For example, an Applesoft file has a file *
* type code of $82 or $02 if it is locked or unlocked. Once the *
* description entry is updated, the modified directory sector is *
* written back to the disk. *
* The verify FUNTION handler work much differently. It *
* opens the file and then read the sectors one at a time into *
* the data sector buffer. As each sector is read, a checksum is *
* calculated by RWTS. If the calculated checksum agrees with *
* the checksum read off the disk, the data are verified. *
* Failure to verify results in an I/O error messge. *
* *
* Although the VERIFY command can be used by itself, it is *
* also called by the INIT, SAVE and BSAVE commands. *
* Unfortunately, the VERIFY command is probably the least *
* understood of all the DOS commands. Because RWTS *
* automatically check the integrity of the data whenever some- *
* thing is read from the disk, it seems that DOS is wasting *
* valuable memory space by supporting the verify command and *
* function handlers. However, when it is used by the INIT, SAVE *
* or BSAVE cmds, the VERIFY routine saves time by checking the *
* file right after it is written. In otherwords, you don't have *
* to LOAD or BLOAD the file just to make sure that all went *
* well. Because the VERIFY command can be used on any type of *
* file, you don't have to write special driver programs to *
* "read" special file types or text files just to be be sure *
* that they were written to the disk correctly. (This later *
* attribute can (under the right conditions) be used as a quick *
* check to see if a protection-concious author has messed around *
* with the checksum bytes.) *
* *
******************************************************************
* On entry - CUMLOPTN ($AA65) has been updated
* to reflect parsed option words (V, D, S).
* - the validity of the options issued
* with the command (and their numeric
* values) have been checked.
* - a legal file name has been parsed and
* stored in the primary file name buffer
* (PRIMFNBF, $AA75).
(A27D)
CMDVERFY LDA #12 ;Verify opcode.
(A27F) BNE LOKUNLOK ;ALWAYS.
(A271)
CMDLOCK LDA #7 ;Lock opcode.
(A273) BNE LOKUNLOK ;ALWAYS.
(A275)
CMDUNLOK LDA #8 ;Unlock opcode.
(A277)
LOKUNLOK JSR HNDLCMD1 ;Call part of the main command handler
;routine to LOCK, UNLOCK or VERIFY
;the file.
* Part of common file manager command handler code.
(A2AA)
HNDLCMD1 STA TEMPBYT ;Store opcode in temporary location.
LDA LENPRSD ;Get L-parameter from parsed table.
BNE SAVLENFM ;Was a non-zero L-parm issued with cmd?
LDA LENPRSD+1
BNE SAVLENFM
LDA #1 ;Length was 0 so make it 1 instead.
STA LENPRSD
SAVLENFM LDA LENPRSD ;Put length in FM parm list.
STA RECLENFM
LDA LENPRSD+1
STA RECLENFM+1
CLSLOCBF JSR CMDCLOSE ;Close file if it's already open.
(A2C8)
(A2EA)
CMDCLOSE .
.
(See dis'mbly of CMDCLOSE given below.)
.
.
- Note that execution flows thru CMDCLOSE twice if the
file is already open.
- The first time thru, the matching DOS filename buffer is
located & then CLOSEONE is used to close the file.
- Execution then jumps back to the start of CMDCLOSE.
- On this second pass, a matching filename is not found
because the DOS filename buffer was released on the
first pass. Therefore, A5L/H is left pointing at the
highest numbered (lowest in memory) FREE DOS buffer
when CMCLOSE is exited via EVENTXIT and CLOSERTS.
- If the file is not already open on the first entry to
CMDCLOSE, only one pass is made. This single pass
resembles the second pass mentioned above.
.
.
- If necessary, the CLOSE FUNCTION updates the data
sector, T/S list sector & the VTOC. It also fixes
up links in the directory sectors and updates the
file size if needed.
.
.
(RTS)
(A2CB) LDA A5L+1 ;Hi byte of A5L/H pointer which points at the highest
;numbered (lowest in memory) free DOS name buffer (in chain).
(A2CD) BNE SAVFNPTR ;Branch if found a free buffer.
(A2CF) JMP NOBUFERR ;Go issue an out-of-buffers message.
------------ ;(See dis'mbly of errors.)
(A2D2)
SAVFNPTR STA A3L+1 ;Reset A3L/H to point at DOS buffer that we
LDA A5L ;will use for file name field buffer (chain).
STA A3L
(A2D8) JSR CPYPFN
* NOTE: This (re)assigns a DOS buffer to the
* file we want to verify, lock or unlock. The
* buffer may or may not be the same one that
* was just released by the CLOSE cmd above.
* The highest numbered (lowest in memory) free
* DOS buffer is used.
(A743)
CPYPFN LDY #29 ;30 bytes to copy (0 to 29).
CPYPRIM LDA PRIMFNBF,Y ;Copy the name of the file wanted from
STA (A3L),Y ;the primary filename buffer into the
DEY ;filename field buffer (in DOS chain).
BPL CPYRIM ;More chars to get.
(A74D) RTS
(A2DB) JSR BUFS2PRM
* Get addresses of the various DOS buffers from the
* chain buffer & put them in the FM parameter list.
(A74E)
BUFS2PRM LDY #30 ;Get addr of FM work buf, T/S list
ADRINPRM LDA (A3L),Y ;buf, data sector buf & next DOS
STA WRKBUFFM-30,Y ;filename buf from chain
INY ;pointer buffer & put them in FM parm list.
CPY #38 ;(P.S. Adr of next DOS file name buf is
BNE ADRINPRM ;not used by DOS.)
(A75A) RTS
(A2DE) JSR CPY2PARM
* Put volume, drive, & slot values plus the
* address of the primary filename buffer
* in the FM parameter list.
(A71A)
CPY2PARM LDA VOLPRSD ;From parsed table.
STA VOLFM
LDA DRVPRSD ;From parsed table.
STA DRVFM
LDA SLOTPRSD ;From parsed table.
STA SLOTFM
LDA ADRPFNBF ;Get the adr of the primary file
STA FNAMBUFM ;name buf from the constants tbl
LDA ADRPFNBF+1 ;and put it in the FM parm list.
STA FNAMBUFM+1
LDA A3L ;Save adr of current DOS file name
STA CURFNADR ;buf in table of DOS variables.
LDA A3L+1
STA CURFNADR+1
(A742) RTS
(A2E1) LDA TEMPBYT ;Get verify, lock or unlock opcode back from temporary
STA OPCODEFM ;buffer & put it in the FM parameter list.
(A2E7) JMP FMDRIVER
------------
* Use the file manager driver to do the
* VERIFY, LOCK or UNLOCK FUNCTIONS.
(A6A8)
FMDRIVER JSR FILEMGR ;Call the file manager to do the function.
* File manager proper.
(AB06)
FILEMGR TSX ;Save stk pointer so can later rtn to caller of FM.
STX STKSAV
(AB0A) JSR RSTRFMWA
* Copy FM work buf (in DOS chain) to
* FM work area (not in DOS chain).
(AE6A)
RSTRFMWA JSR SELWKBUF ;Point A4L/H at FM work buf.
* Get addr of FM work buff from
* the FM parm list & put it in
* the A4L/H pointer.
(AF08)
SELWKBUF LDX #0 ;Offset to select
;work buffer.
(AF0A) BEQ PT2FMBUF ;ALWAYS.
(AF12)
PT2FMBUF LDA WRKBUFFM,X
STA A4L
LDA WRKBUFFM+1,X
STA A4L+1
(AF1C) RTS
(AE6D) LDY #0 ;Zero out return code in FM parm list to
STY RTNCODFM ;signal no errors as default condition.
STORFMWK LDA (A4L),Y ;Copy FM work buf to FM work area.
STA FMWKAREA,Y
INY
CPY #45 ;45 bytes to copy (0 to 44).
BNE STORFMWK
CLC ;WHY?????
(AE7D) RTS
(AB0D) LDA OPCODEFM ;Check if opcode is legal.
CMP #13 ;(Must be less than 13.)
BCS TOERROP ;Opcode too large so got range error.
ASL ;Double val of opcode & put it in (x)
TAX ;so it indexes tables of adrs.
LDA FMFUNCTB+1,X ;Stick adr of appropriate function
PHA ;handler on stack (hi byte first).
LDA FMFUNCTB,X
PHA
(AB1E) RTS ;DO STACK JUMP TO FUNCTION ENTRY POINT.
.
.
(See dis'mbly of the appropriate function.)
.
.
RE: LOCK OR UNLOCK FUNCTION.
- uses part of COMNOPEN routine.
- reads in VTOC to get link to 1rst directory.
- reads directory secs in & looks for file
description entry with matching filename.
- if matching name found, modifies the file
type code with LOKUNMSK ($B39E) to denote
a locked or unlocked file.
- writes updated directory sector buffer to disk.
.
.
RE: VERIFY FUNCTION.
- reads in VTOC & appropriate directory, T/S list
& data sectors.
- The verify function simply opens & then reads
a file. Actual verification occurs deep within
RWTS. As the data are read in, a checksum is
calculated. If the calculated checksum agrees
with the checksum read off the disk, the integrity
of the data is verified. Failure to verify yeilds
an I/O error.
.
.
(RTS)
============
TOERROP JMP RNGERROP ;Go handle range error.
(AB1F) ------------ ;(See dis'mbly of errors.)
* Return here after doing the verify, lock
* or unlock functions. (Cause after @
* function is done, use stack to get back
* to the original caller.)
(A6AB)
AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors.
LDA RTNCODFM ;Get error code from FM parameter list.
CMP #$5 ;End of data error?
(A6B2) BEQ TOAPPTCH ;Yes - Encountered a zeroed-out T/S link or
;a zeroed-out data pair (trk/sec vals)
;listed in the T/S list. (Not applicable
;to the lock, unlock or verify functions.)
(A6B4) JMP OTHRERR ;Got an error other than an end-of-data error.
------------ ;(See dis'mbly of errors.)
(A6C3)
FMDRVRTN RTS
(A27A) JMP CMDCLOSE ;Go back into CMDCLOSE to close the
------------ ;file that was just opened via the
;verify, lock or unlock function.
* Because the file is already open, execution flows
* thru the close cmd twice. The first time thru, the matching
* DOS filename buffer is located & then CLOSEONE is used to
* close the file via the close FUNCTION. The 2nd time thru, a
* matching filename buffer is not found because the DOS
* buffer was released on the first pass. Therefore, A5L/H is
* left pointing at the highest numbered (lowest in memory)
* FREE DOS buffer when the close command is exited via EVENTXIT
* and CLOSERTS.
*
* (P.S. NOT ALL RAMIFICATIONS OF THE CLOSE COMMAND ARE SHOWN
* BELOW.)
(A2EA)
CMDCLOSE LDA PRIMFNBF ;Get 1rst char from primary name buffer.
CMP #" " ;Don't allow leading <spc> in name.
(A2EF) BEQ CLOSEALL ;Leading <spc> = signal to close all files.
;(A close cmd was issued with no
;accompanying file name.)
(A2F1) JSR GETBUFF ;Locate a DOS file buffer.
* Locate buffer with same name.
* If that fails, locate a free buffer.
(A764)
GETBUFF LDA #0 ;Default hi-byte of pointer to 0
STA A5L+1 ;(ie. assume no free buff available).
(A768) JSR GETFNBF1 ;Get pointer to 1rst filename buffer in chain.
(A792)
GETFNBF1 LDA ADOSFNB1 ;First link to chain of DOS buffers
LDX ADOSFNB1+1 ;(ie. pt 2 1rst name buf in chain).
(A798) BNE SETNXPTR ;ALWAYS.
(A7A4)
SETNXPTR STX A3L+1 ;Put addr of 1rst filename buffer in ptr
STA A3L ;(ie. highest name buffer in chain).
TXA ;Get hi-byte of addr in back in (a).
GETNXRTN RTS
(A7A9)
(A76B) JMP FNCHAR1 ;Get first byte from DOS name buf.
------------
(A76E)
GETFNLNK JSR GETNXBUF
* Get addr of next filename buffer in chain
* from chain pointers buffer offset 37 & 36
* bytes from 1rst char of present filename
* buffer.
(A79A)
GETNXBUF LDY #37 ;Point the pointer at the chain buffer &
LDA (A3L),Y ;get addr of the next filename buffer.
BEQ GETNXRTN ;If hi-byte is 0, then link zeroed out.
TAX ;Save hi-byte in (x).
DEY ;Pick up low-byte.
LDA (A3L),Y
SETNXPTR STX A3L+1 ;Stick addr of filename buffer in ptr.
STA A3L
TXA ;Get hi-byte back in (a).
GETNXRTN RTS
(A7A9)
(A771) BEQ NOFNMTCH ;Link zeroed out, end of chain.
FNCHAR1 JSR GETFNBY1 ;Get the 1rst char of filename from buf in chain.
(A773)
* Get first byte of DOS name buffer.
(A7AA)
GETFNBY1 LDY #0 ;Buffer is free if 1rst byte = $00.
LDA (A3L),Y ;If buf occuppied, the 1rst byte = 1rst
(A7AE) RTS ;char of filename which owns buffer.
(A776) BNE NXFNBUF ;Take branch if buffer wasn't free.
LDA A3L ;Buffer was free, there4 point the A5L/H
STA A5L ;pointer at the free buffer.
LDA A3L+1
STA A5L+1
(A780) BNE GETFNLNK ;ALWAYS.
(A782)
NXFNBUF LDY #29 ;Buffer not free there4 compare name
CMPFNCHR LDA (A3L),Y ;of owner with name of file in primary
CMP PRIMFNBF,Y ;name buffer. (Start with last char first.)
(A789) BNE GETFNLNK ;Char doesn't match, there4 look for another
;buffer that might have same name.
(A78B) DEY ;That char matched, how bout rest of name?
BPL CMPFNCHR ;30 chars in name (ie. 0 to 29).
CLC ;Clr carry to signal that names match.
(A78F) RTS
============
(A790)
NOFNMTCH SEC ;Link zeroed out.
(A791) RTS
============
(A2F4)
EVENTXIT BCS CLOSERTS ;EVENTUALLY exit via this route.
(A2F6) JSR CLOSEONE ;Matching file name was found, so close that file.
* Close a particular file.
(A2FC)
CLOSEONE JSR CKEXCBUF
* Check if current filename buffer
* belongs to an EXEC file. After all,
* don't want to close buffer if we are
* using it to exec (ie. would be like
* burying ourselves alive).
(A7AF)
CKEXCBUF LDA EXECFLAG ;Check to see if EXECing.
BEQ NOTEXCBF ;No sweat - not running exec file.
LDA EXECBUFF ;We are EXECing, there4 chk if addr of
CMP A3L ;current filename buffer same as that
BNE CKEXCRTN ;for buffer belonging to EXEC.
LDA EXECBUFF+1 ;Maybe - low-bytes matched,
CMP A3L+1 ;so now check hi bytes of addr.
BEQ CKEXCRTN ;Exec buffer = current buffer.
NOTEXCBF DEX ;Not EXECing, DEX to make sure z-flag off.
(A7C2) ;(P.S. (x) was orig set to large non-zero
;val on entry to GETFNBF1. There4, if now
;DEX, can be sure z-flag will be off.)
CKEXCRTN RTS ;Exit with z-flag = 1 if execing.
(A7C3) ; = 0 if not execing.
(A2FF) BNE FREEBUFF ;Not EXECing from this particular file.
LDA #0 ;Closing an exec file so shut
STA EXECFLAG ;off the exec flag.
FREEBUFF LDY #0 ;Free up the DOS buffer by poking a $00 in
TYA ;1rst byte of filename.
STA (A3L),Y
(A30B) JSR BUFS2PRM
* GET addresses of the DOS buffers from chain
* buffer & put them in FM parameter list.
(A74E)
BUFS2PRM LDY #30 ;Get addresses of FM Work buffer,
ADRINPRM LDA (A3L),Y ;T/S list buffer, Data sec buffer and
STA WRKBUFFM-30,Y ;NEXT filename buf from the chain ptr
INY ;buf & put them in the FM parameter list.
CPY #38 ;(P.S. addr of NEXT filename buffer
BNE ADRINPRM ;is not used by DOS.)
(A75A) RTS
(A30E) LDA #2 ;Stick opcode for CLOSE function
STA OPCODEFM ;in the FM parameter list.
(A313) JMP FMDRIVER ;Get ready to do the function.
------------
(A6A8)
FMDRIVER JSR FILEMGR ;Call the file manager to do the function.
(AB06)
FILEMGR TSX ;Save stk ptr so we can rtn to caller.
STX STKSAV
(AB0A) JSR RSTRFMWA ;Copy contents of FM work buffer (in DOS
;chain) to FM work area (not in chain).
(AE6A)
RSTRFMWA JSR SELWKBUF ;Find FM work buffer.
* Get address of FM work buffer (chain)
* from the FM parameter list & stick
* it in the A4L/H pointer.
(AF08)
SELWKBUF LDA #0
(AF0A) BEQ PT2FMBUF ;ALWAYS.
(AF12)
PT2FMBUF LDA WRKBUFFM,X
STA A4L
LDA WRKBUFFM+1,X
STA A4L+1
(AF1C) RTS
(AE6D) LDY #0 ;Zero-out rtn code in FM parm
STY RTNCODFM ;list to signal no errors.
STORFMWK LDA (A4L),Y ;Copy FM work buf (in chain) to the FM
STA FMWKAREA,Y ;work area (not in DOS buffer chain).
INY
CPY #45
BNE STORFMWK
CLC ;Why?????
(AE7D) RTS
(AB0D) LDA OPCODEFM ;Chk if opcode is legal.
CMP #13 ;(Must be less than 13.)
BCS TOERROP ;Opcode too large, got range error.
ASL ;Double val of opcode & get addr of
TAX ;appropriate function handler from tbl.
LDA FMFUNCTB+1,X ;Put the adr on stack (hi byte first)
PHA ;& then do a "stack jump" to the appropriate
LDA FMFUNCTB,X ;function handler.
PHA
(AB1E) RTS
.
.
(AC06) .
FNCLOSE .
.
.
(See dis'mbly of CLOSE function.)
.
.
- if necessary, free up any sectors that
were previously allocated to the file
but not needed.
- also updates the file size, fixes up
links & updates data, VTOC, T/S list
& directory sectors if necessary.
.
.
(RTS)
============
TOERROP JMP RNGERROP ;(To $B363 - see dis'mbly of errors.)
(AB1F) ------------
* Return here after doing the close function
* (Cause after @ function is done, use stack
* to get back to original caller.)
(A6AB)
AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors.
LDA RTNCODFM ;Get error code from FM parameter list.
CMP #$5 ;End of data error?
(A6B2) BEQ TOAPPTCH ;Yes - Encountered a zeroed-out T/S link or
;a zeroed-out data pair (trk/sec vals)
;listed in the T/S list. (Not applicable to
;the close function.)
(A6B4) JMP OTHRERR ;Got an error other than an end-of-data error.
------------ ;(See dis'mbly of errors.)
(A6C3)
FMDRVRTN RTS
(A2F9) JMP CMDCLOSE ;Go back into CMDCLOSE to point the A5L/H
------------ ;pointer at the highest numbered (lowest in
;memory) free filename buffer in chain of
;DOS buffers & then exit CMDCLOSE & CMDVERFY
;(or CMDLOCK or CMDUNLOK) via EVENTXIT &
;CLOSERTS.
(A330)
CLOSERTS RTS ;Exit to caller of command.
============ ;(Normally returns to AFTRCMD ($A17D) in the
;command parsing and processing routines.)

View File

@@ -0,0 +1,102 @@
<HTML>
<TITLE>T E X T F I L E S</TITLE>
<BODY BGCOLOR="#000000" TEXT="#00FF00" LINK="#00FF00" ALINK="#00AA00" VLINK="#00AA00">
<H1>Apple II: Cracking</H1>
<P>
When pirating Apple II games, the challenge was to make it as easy to transfer the
files as possible. Since 300 baud could mean a full disk transfer taking over an
hour, any reduction in size would be welcomed.
<P>
One way to do this would be to take a program disk and turn the disk into a single,
smaller file. Of course, most programs (especially games) would have protection
schemes inside to check to see if this sort of manipulaiton had gone on. Enter the
"Crackers", who would "Crack" the protection schemes so they didn't work anymore.
<P>
This battle waged and has continued to wage between Software Companies and Software
Pirates.
<P>
<TABLE WIDTH=100%>
<TD BGCOLOR=#00FF00><FONT COLOR=#000000><B>Filename</B><BR></FONT></TD>
<TD BGCOLOR=#00DD00><FONT COLOR=#000000><B>Size</B><BR></FONT></TD>
<TD BGCOLOR=#00AA00><FONT COLOR=#000000><B>Description of the Textfile</B><BR></TD></TR>
<tab indent=60 id=T><br>
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/addocs.txt">addocs.txt</A> <tab to=T><TD> 17769<BR><TD> DOCS: Advanced Demuffin Version 1.1 by The Stack and The Inspector (February 8, 1983)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/adexample.txt">adexample.txt</A> <tab to=T><TD> 2682<BR><TD> An Example of Using Advanced Demuffin to Crack a Game: Castle Wolfenstein
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/adtech.txt">adtech.txt</A> <tab to=T><TD> 16773<BR><TD> Technical Notes for Advanced Demuffin 1.1 by The Stack (1983)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/advdem.app">advdem.app</A> <tab to=T><TD> 16645<BR><TD> Technical notes for Advanced DeMuffin II, a cracking tool
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/alienmdcheat.txt">alienmdcheat.txt</A> <tab to=T><TD> 1286<BR><TD> Alien Mind Cheat - Brought to you by The Baron
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/alienmindpatch.txt">alienmindpatch.txt</A> <tab to=T><TD> 2183<BR><TD> A Crack and patch for Alien Mind, from Fred Gotfredson
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/asstcracks1.txt">asstcracks1.txt</A> <tab to=T><TD> 8806<BR><TD> Assorted Cracks 1: Wings of Fury, VCR Companion, CrossWord Magic 4.0, Tetris, RoboCop, Ikari Warriors, etc. from Michael Kelsey
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/asstcracks2.txt">asstcracks2.txt</A> <tab to=T><TD> 11043<BR><TD> Assorted Cracks 2: From Mike Hackett
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/bardst3wheel.txt">bardst3wheel.txt</A> <tab to=T><TD> 565<BR><TD> Bard's Tale III Code Wheel crack,from Zhu Hang
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/bardstale.txt">bardstale.txt</A> <tab to=T><TD> 8219<BR><TD> Bard's Tale I and II GS character editor
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/battlechess.txt">battlechess.txt</A> <tab to=T><TD> 1084<BR><TD> Deprotect for Battle Chess
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/bubbleghost.txt">bubbleghost.txt</A> <tab to=T><TD> 3680<BR><TD> Bubble Ghost from Accolade
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/cheat.app">cheat.app</A> <tab to=T><TD> 4424<BR><TD> All manner of cheats for various Apple II games
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/cheats">cheats</A> <tab to=T><TD> 7416<BR><TD> LARGE Collection of Apple Cheats (Break into Monitor and Modify)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/cheats.app">cheats.app</A> <tab to=T><TD> 2749<BR><TD> The Penguin's Apple Cheats
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/cheats2.app">cheats2.app</A> <tab to=T><TD> 4498<BR><TD> Apple Pirate's Cheats
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/chess2000.txt">chess2000.txt</A> <tab to=T><TD> 1493<BR><TD> ChessMaster 2100 GS
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/copyprog.app">copyprog.app</A> <tab to=T><TD> 2991<BR><TD> How to Copy Programs, by the Three Musketeers
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/copyprot.app">copyprot.app</A> <tab to=T><TD> 15163<BR><TD> Copy-Protecting your own disks, by Thomas T. Brylinski
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/crack1.txt">crack1.txt</A> <tab to=T><TD> 1023<BR><TD> Introduction to a Talk on Software Piracy
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/crackin.app">crackin.app</A> <tab to=T><TD> 9989<BR><TD> An introduction to cracking by The Necromancer
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/cracktutor.txt">cracktutor.txt</A> <tab to=T><TD> 9295<BR><TD> The Basics of Basic Cracking, by Copy/Cat of the Hi-Res Hijackers
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/crakowit.app">crakowit.app</A> <tab to=T><TD> 3647<BR><TD> Kracowicz' Kracking Corner IV
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/crisis.app">crisis.app</A> <tab to=T><TD> 1900<BR><TD> How to crack Crisis Mountain, by Doctor Who
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/crisismtncrack.txt">crisismtncrack.txt</A> <tab to=T><TD> 1922<BR><TD> How to Crack Crisis Mountain
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/darkheart.txt">darkheart.txt</A> <tab to=T><TD> 6468<BR><TD> Become Master of the Game! Breaking into The Dark Heart of Uukrul by Jeff Hurlburt
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/deathcheat">deathcheat</A> <tab to=T><TD> 517<BR><TD> Cheat for "Death Sword"
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/dejavucracks.txt">dejavucracks.txt</A> <tab to=T><TD> 849<BR><TD> Deju Vu cracks from Computist magazine
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/diskjock.app">diskjock.app</A> <tab to=T><TD> 51504<BR><TD> Examining protected Applesoft programs, by the Disk Jockey
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/dm2copy.txt">dm2copy.txt</A> <tab to=T><TD> 682<BR><TD> Deprotect Dungeon Master v2.0
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/fastbreak.txt">fastbreak.txt</A> <tab to=T><TD> 1143<BR><TD> Fastbreak GS by Accolade
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/gnarlygolfcheat.txt">gnarlygolfcheat.txt</A> <tab to=T><TD> 962<BR><TD> Gnarly Golf GS cheat - Britanicca by Jim Maricondo
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/hdinstallmethod.txt">hdinstallmethod.txt</A> <tab to=T><TD> 10700<BR><TD> Install HD Version 1.0 May 1991
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/hot_rods_tfile_1.txt">hot_rods_tfile_1.txt</A> <tab to=T><TD> 15568<BR><TD> Hot Rod's Goodbye to the Scene, by Hot Rod of Black Bag (April 4, 1986)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/immortaldepro.txt">immortaldepro.txt</A> <tab to=T><TD> 2487<BR><TD> Deprotecting The Immortal
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/infohardware.txt">infohardware.txt</A> <tab to=T><TD> 13996<BR><TD> Krakowicz' Kracking Korner: Basic Hardware Kracking Tools
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/infolost.txt">infolost.txt</A> <tab to=T><TD> 6615<BR><TD> The Lost Treasures of Infocom Mini Manual
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/inforomswitch.txt">inforomswitch.txt</A> <tab to=T><TD> 4970<BR><TD> Instructions for the Romswitch and the Krakrom NMI, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/jacknicklausgolf.txt">jacknicklausgolf.txt</A> <tab to=T><TD> 749<BR><TD> Jack Nicklaus's Greatest 18 Holes of Major Championship Golf
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krack1.app">krack1.app</A> <tab to=T><TD> 2927<BR><TD> High Technology's Cracking Tutorial, Part I
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krack2.app">krack2.app</A> <tab to=T><TD> 1765<BR><TD> High Technology's Cracking Tutorial, Part II
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krack3.app">krack3.app</A> <tab to=T><TD> 2239<BR><TD> High Technology's Cracking Tutorial, Part III
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krack4.app">krack4.app</A> <tab to=T><TD> 1887<BR><TD> High Technology's Cracking Tutorial, Part IV
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krack5.app">krack5.app</A> <tab to=T><TD> 2560<BR><TD> High Technology's Cracking Tutorial, Part V
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackarcade.txt">krackarcade.txt</A> <tab to=T><TD> 11096<BR><TD> Krakowicz's Kracking Korner IV: The Arcade Machine, with Notes on NMI and IDSI's Juggler, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackcyclod.txt">krackcyclod.txt</A> <tab to=T><TD> 18184<BR><TD> Krakowicz' Kraking Corner: Cyclod, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackcyclod2.txt">krackcyclod2.txt</A> <tab to=T><TD> 12219<BR><TD> Krakowicz' Kracking Corner: Cyclod and Juggler, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackspm.txt">krackspm.txt</A> <tab to=T><TD> 13745<BR><TD> Krakowicz' Kracking Korner: Kameari from Ado-Soft (Japan)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackssi.txt">krackssi.txt</A> <tab to=T><TD> 16351<BR><TD> Krakowicz' Kracking Korner: SSI's RDOS, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/kracktypea.txt">kracktypea.txt</A> <tab to=T><TD> 24839<BR><TD> Dealing with Disk Access Routines, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackwo.txt">krackwo.txt</A> <tab to=T><TD> 8266<BR><TD> Krakowicz' Kracking Corner IIIa: Way Out, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krackwo2.txt">krackwo2.txt</A> <tab to=T><TD> 7269<BR><TD> Krakowicz' Kraking Corner: Way Out Part 2, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krakowic.txt">krakowic.txt</A> <tab to=T><TD> 13198<BR><TD> Kracowicz' Kraking Tips from ROM Raider
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/krckwczt.app">krckwczt.app</A> <tab to=T><TD> 137510<BR><TD> The Kracowicz Basics of Cracking Series. A++
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/lastninjaonhd.txt">lastninjaonhd.txt</A> <tab to=T><TD> 1770<BR><TD> Last Ninja/IIgs Deprotect and Hard Disk Mods
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/maccrack.app">maccrack.app</A> <tab to=T><TD> 5981<BR><TD> The Byte's introduction to Mac Cracking
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/machine.app">machine.app</A> <tab to=T><TD> 13084<BR><TD> Black Bag's Introduction to Machine Language for Cracking
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/macteam.app">macteam.app</A> <tab to=T><TD> 9569<BR><TD> Macteam's thoughts on copy protection on the Macintosh
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/manycheats2.txt">manycheats2.txt</A> <tab to=T><TD> 20106<BR><TD> Many Cheats II, from Pirates Bay
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/miffins2.txt">miffins2.txt</A> <tab to=T><TD> 1421<BR><TD> How to use Demuffin Plus
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/odysseydepro.txt">odysseydepro.txt</A> <tab to=T><TD> 1246<BR><TD> Odyssey: The Compleat Adventure (Deprotection)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/param2.app">param2.app</A> <tab to=T><TD> 16201<BR><TD> Parameters of Nibbles Away II for various software packages
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/piratesdeproandhd.txt">piratesdeproandhd.txt</A> <tab to=T><TD> 9838<BR><TD> Making Pirates/GS Hard Disk Bootable, by Rubywant
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/playroomdepro.txt">playroomdepro.txt</A> <tab to=T><TD> 1710<BR><TD> A Backup for Playroom, by Broderbund
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/princepersiadepro.txt">princepersiadepro.txt</A> <tab to=T><TD> 2243<BR><TD> Deprotect for Prince of Persia on 3.5" Floppy
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/softkey">softkey</A> <tab to=T><TD> 21083<BR><TD> Softkey Unprotections for a Variety of Commercial Programs
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/tangled.txt">tangled.txt</A> <tab to=T><TD> 2888<BR><TD> Deprotect for Tangled Tales
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/thexder.txt">thexder.txt</A> <tab to=T><TD> 1201<BR><TD> Old version Thexder joystick patch for IIgs
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/trace2.app">trace2.app</A> <tab to=T><TD> 11562<BR><TD> Mr. Xerox' boot tracing, volume I (badly converted)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/tstdrv28biltdepro.txt">tstdrv28biltdepro.txt</A> <tab to=T><TD> 363<BR><TD> Deprotect for the 8 bit version of Test Drive II
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/ultima.v.txt">ultima.v.txt</A> <tab to=T><TD> 1097<BR><TD> Copy II+ Parameters for Ultima V
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/wings.fury.cht">wings.fury.cht</A> <tab to=T><TD> 606<BR><TD> Cheat to Wings of Fure
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/wiz4codesinfo.txt">wiz4codesinfo.txt</A> <tab to=T><TD> 3575<BR><TD> Wizardry IV Codes
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/wiz5codes.txt">wiz5codes.txt</A> <tab to=T><TD> 37590<BR><TD> Wizardry V Magic Word List
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/wpwiz1dsk.txt">wpwiz1dsk.txt</A> <tab to=T><TD> 1372<BR><TD> Adding Write-Protect to Wizardry I boot disk image
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/xenocide.txt">xenocide.txt</A> <tab to=T><TD> 925<BR><TD> Xenocide "key-disk" removal patch
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/yscheat.txt">yscheat.txt</A> <tab to=T><TD> 5179<BR><TD> Cheat for Ancient Land of Y's (GS) by Jim Maricondo
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="CRACKING/ysdepro.txt">ysdepro.txt</A> <tab to=T><TD> 6834<BR><TD> Crack for Ancient Land of Y's (GS) by Jim Maricondo
</TABLE><P><TABLE WIDTH=100%><TR><TD ALIGN=RIGHT><SMALL>There are 78 files for a total of 725,954 bytes.</SMALL></TABLE>

View File

@@ -0,0 +1,101 @@
<HTML>
<TITLE>T E X T F I L E S</TITLE>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#000000" ALINK="#004400" VLINK="#004400">
<H1>Apple II: Cracking</H1>
<P>
When pirating Apple II games, the challenge was to make it as easy to transfer the
files as possible. Since 300 baud could mean a full disk transfer taking over an
hour, any reduction in size would be welcomed.
<P>
One way to do this would be to take a program disk and turn the disk into a single,
smaller file. Of course, most programs (especially games) would have protection
schemes inside to check to see if this sort of manipulaiton had gone on. Enter the
"Crackers", who would "Crack" the protection schemes so they didn't work anymore.
<P>
This battle waged and has continued to wage between Software Companies and Software
Pirates.
<P>
<TABLE WIDTH=100%>
<TD BGCOLOR=#000000><FONT COLOR=#FFFFFF><B>Filename</B><BR></FONT></TD>
<TD BGCOLOR=#002200><FONT COLOR=#FFFFFF><B>Size</B><BR></FONT></TD>
<TD BGCOLOR=#004400><FONT COLOR=#FFFFFF><B>Description of the Textfile</B><BR></TD></TR>
<tab indent=60 id=T><br>
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="addocs.txt">addocs.txt</A> <tab to=T><TD> 17769<BR><TD> DOCS: Advanced Demuffin Version 1.1 by The Stack and The Inspector (February 8, 1983)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="adexample.txt">adexample.txt</A> <tab to=T><TD> 2682<BR><TD> An Example of Using Advanced Demuffin to Crack a Game: Castle Wolfenstein
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="adtech.txt">adtech.txt</A> <tab to=T><TD> 16773<BR><TD> Technical Notes for Advanced Demuffin 1.1 by The Stack (1983)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="advdem.app">advdem.app</A> <tab to=T><TD> 16645<BR><TD> Technical notes for Advanced DeMuffin II, a cracking tool
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="alienmdcheat.txt">alienmdcheat.txt</A> <tab to=T><TD> 1286<BR><TD> Alien Mind Cheat - Brought to you by The Baron
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="alienmindpatch.txt">alienmindpatch.txt</A> <tab to=T><TD> 2183<BR><TD> A Crack and patch for Alien Mind, from Fred Gotfredson
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="asstcracks1.txt">asstcracks1.txt</A> <tab to=T><TD> 8806<BR><TD> Assorted Cracks 1: Wings of Fury, VCR Companion, CrossWord Magic 4.0, Tetris, RoboCop, Ikari Warriors, etc. from Michael Kelsey
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="asstcracks2.txt">asstcracks2.txt</A> <tab to=T><TD> 11043<BR><TD> Assorted Cracks 2: From Mike Hackett
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="bardst3wheel.txt">bardst3wheel.txt</A> <tab to=T><TD> 565<BR><TD> Bard's Tale III Code Wheel crack,from Zhu Hang
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="bardstale.txt">bardstale.txt</A> <tab to=T><TD> 8219<BR><TD> Bard's Tale I and II GS character editor
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="battlechess.txt">battlechess.txt</A> <tab to=T><TD> 1084<BR><TD> Deprotect for Battle Chess
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="bubbleghost.txt">bubbleghost.txt</A> <tab to=T><TD> 3680<BR><TD> Bubble Ghost from Accolade
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="cheat.app">cheat.app</A> <tab to=T><TD> 4424<BR><TD> All manner of cheats for various Apple II games
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="cheats">cheats</A> <tab to=T><TD> 7416<BR><TD> LARGE Collection of Apple Cheats (Break into Monitor and Modify)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="cheats.app">cheats.app</A> <tab to=T><TD> 2749<BR><TD> The Penguin's Apple Cheats
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="cheats2.app">cheats2.app</A> <tab to=T><TD> 4498<BR><TD> Apple Pirate's Cheats
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="chess2000.txt">chess2000.txt</A> <tab to=T><TD> 1493<BR><TD> ChessMaster 2100 GS
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="copyprog.app">copyprog.app</A> <tab to=T><TD> 2991<BR><TD> How to Copy Programs, by the Three Musketeers
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="copyprot.app">copyprot.app</A> <tab to=T><TD> 15163<BR><TD> Copy-Protecting your own disks, by Thomas T. Brylinski
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="crack1.txt">crack1.txt</A> <tab to=T><TD> 1023<BR><TD> Introduction to a Talk on Software Piracy
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="crackin.app">crackin.app</A> <tab to=T><TD> 9989<BR><TD> An introduction to cracking by The Necromancer
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="cracktutor.txt">cracktutor.txt</A> <tab to=T><TD> 9295<BR><TD> The Basics of Basic Cracking, by Copy/Cat of the Hi-Res Hijackers
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="crakowit.app">crakowit.app</A> <tab to=T><TD> 3647<BR><TD> Kracowicz' Kracking Corner IV
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="crisis.app">crisis.app</A> <tab to=T><TD> 1900<BR><TD> How to crack Crisis Mountain, by Doctor Who
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="crisismtncrack.txt">crisismtncrack.txt</A> <tab to=T><TD> 1922<BR><TD> How to Crack Crisis Mountain
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="darkheart.txt">darkheart.txt</A> <tab to=T><TD> 6468<BR><TD> Become Master of the Game! Breaking into The Dark Heart of Uukrul by Jeff Hurlburt
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="deathcheat">deathcheat</A> <tab to=T><TD> 517<BR><TD> Cheat for "Death Sword"
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="dejavucracks.txt">dejavucracks.txt</A> <tab to=T><TD> 849<BR><TD> Deju Vu cracks from Computist magazine
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="diskjock.app">diskjock.app</A> <tab to=T><TD> 51504<BR><TD> Examining protected Applesoft programs, by the Disk Jockey
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="dm2copy.txt">dm2copy.txt</A> <tab to=T><TD> 682<BR><TD> Deprotect Dungeon Master v2.0
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="fastbreak.txt">fastbreak.txt</A> <tab to=T><TD> 1143<BR><TD> Fastbreak GS by Accolade
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="gnarlygolfcheat.txt">gnarlygolfcheat.txt</A> <tab to=T><TD> 962<BR><TD> Gnarly Golf GS cheat - Britanicca by Jim Maricondo
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="hdinstallmethod.txt">hdinstallmethod.txt</A> <tab to=T><TD> 10700<BR><TD> Install HD Version 1.0 May 1991
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="immortaldepro.txt">immortaldepro.txt</A> <tab to=T><TD> 2487<BR><TD> Deprotecting The Immortal
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="infohardware.txt">infohardware.txt</A> <tab to=T><TD> 13996<BR><TD> Krakowicz' Kracking Korner: Basic Hardware Kracking Tools
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="infolost.txt">infolost.txt</A> <tab to=T><TD> 6615<BR><TD> The Lost Treasures of Infocom Mini Manual
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="inforomswitch.txt">inforomswitch.txt</A> <tab to=T><TD> 4970<BR><TD> Instructions for the Romswitch and the Krakrom NMI, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="jacknicklausgolf.txt">jacknicklausgolf.txt</A> <tab to=T><TD> 749<BR><TD> Jack Nicklaus's Greatest 18 Holes of Major Championship Golf
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krack1.app">krack1.app</A> <tab to=T><TD> 2927<BR><TD> High Technology's Cracking Tutorial, Part I
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krack2.app">krack2.app</A> <tab to=T><TD> 1765<BR><TD> High Technology's Cracking Tutorial, Part II
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krack3.app">krack3.app</A> <tab to=T><TD> 2239<BR><TD> High Technology's Cracking Tutorial, Part III
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krack4.app">krack4.app</A> <tab to=T><TD> 1887<BR><TD> High Technology's Cracking Tutorial, Part IV
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krack5.app">krack5.app</A> <tab to=T><TD> 2560<BR><TD> High Technology's Cracking Tutorial, Part V
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackarcade.txt">krackarcade.txt</A> <tab to=T><TD> 11096<BR><TD> Krakowicz's Kracking Korner IV: The Arcade Machine, with Notes on NMI and IDSI's Juggler, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackcyclod.txt">krackcyclod.txt</A> <tab to=T><TD> 18184<BR><TD> Krakowicz' Kraking Corner: Cyclod, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackcyclod2.txt">krackcyclod2.txt</A> <tab to=T><TD> 12219<BR><TD> Krakowicz' Kraking Corner: Cyclod and Juggler, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackspm.txt">krackspm.txt</A> <tab to=T><TD> 13745<BR><TD> Krakowicz' Kraking Korner: Kameari from Ado-Soft (Japan)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackssi.txt">krackssi.txt</A> <tab to=T><TD> 16351<BR><TD> Krakowicz' Kraking Korner: SSI's RDOS, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="kracktypea.txt">kracktypea.txt</A> <tab to=T><TD> 24839<BR><TD> Dealing with Disk Access Routines, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackwo.txt">krackwo.txt</A> <tab to=T><TD> 8266<BR><TD> Krakowicz' Kraking Corner IIIa: Way Out, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krackwo2.txt">krackwo2.txt</A> <tab to=T><TD> 7269<BR><TD> Krakowicz' Kraking Corner: Way Out Part 2, by Krakowicz
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krakowic.txt">krakowic.txt</A> <tab to=T><TD> 13198<BR><TD> Kracowicz' Kraking Tips from ROM Raider
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="krckwczt.app">krckwczt.app</A> <tab to=T><TD> 137510<BR><TD> The Kracowicz Basics of Cracking Series. A++
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="lastninjaonhd.txt">lastninjaonhd.txt</A> <tab to=T><TD> 1770<BR><TD> Last Ninja/IIgs Deprotect and Hard Disk Mods
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="maccrack.app">maccrack.app</A> <tab to=T><TD> 5981<BR><TD> The Byte's introduction to Mac Cracking
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="machine.app">machine.app</A> <tab to=T><TD> 13084<BR><TD> Black Bag's Introduction to Machine Language for Cracking
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="macteam.app">macteam.app</A> <tab to=T><TD> 9569<BR><TD> Macteam's thoughts on copy protection on the Macintosh
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="manycheats2.txt">manycheats2.txt</A> <tab to=T><TD> 20106<BR><TD> Many Cheats II, from Pirates Bay
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="miffins2.txt">miffins2.txt</A> <tab to=T><TD> 1421<BR><TD> How to use Demuffin Plus
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="odysseydepro.txt">odysseydepro.txt</A> <tab to=T><TD> 1246<BR><TD> Odyssey: The Compleat Adventure (Deprotection)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="param2.app">param2.app</A> <tab to=T><TD> 16201<BR><TD> Parameters of Nibbles Away II for various software packages
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="piratesdeproandhd.txt">piratesdeproandhd.txt</A> <tab to=T><TD> 9838<BR><TD> Making Pirates/GS Hard Disk Bootable, by Rubywant
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="playroomdepro.txt">playroomdepro.txt</A> <tab to=T><TD> 1710<BR><TD> A Backup for Playroom, by Broderbund
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="princepersiadepro.txt">princepersiadepro.txt</A> <tab to=T><TD> 2243<BR><TD> Deprotect for Prince of Persia on 3.5" Floppy
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="softkey">softkey</A> <tab to=T><TD> 21083<BR><TD> Softkey Unprotections for a Variety of Commercial Programs
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="tangled.txt">tangled.txt</A> <tab to=T><TD> 2888<BR><TD> Deprotect for Tangled Tales
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="thexder.txt">thexder.txt</A> <tab to=T><TD> 1201<BR><TD> Old version Thexder joystick patch for IIgs
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="trace2.app">trace2.app</A> <tab to=T><TD> 11562<BR><TD> Mr. Xerox' boot tracing, volume I (badly converted)
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="tstdrv28biltdepro.txt">tstdrv28biltdepro.txt</A> <tab to=T><TD> 363<BR><TD> Deprotect for the 8 bit version of Test Drive II
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="ultima.v.txt">ultima.v.txt</A> <tab to=T><TD> 1097<BR><TD> Copy II+ Parameters for Ultima V
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="wings.fury.cht">wings.fury.cht</A> <tab to=T><TD> 606<BR><TD> Cheat to Wings of Fure
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="wiz4codesinfo.txt">wiz4codesinfo.txt</A> <tab to=T><TD> 3575<BR><TD> Wizardry IV Codes
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="wiz5codes.txt">wiz5codes.txt</A> <tab to=T><TD> 37590<BR><TD> Wizardry V Magic Word List
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="wpwiz1dsk.txt">wpwiz1dsk.txt</A> <tab to=T><TD> 1372<BR><TD> Adding Write-Protect to Wizardry I boot disk image
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="xenocide.txt">xenocide.txt</A> <tab to=T><TD> 925<BR><TD> Xenocide "key-disk" removal patch
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="yscheat.txt">yscheat.txt</A> <tab to=T><TD> 5179<BR><TD> Cheat for Ancient Land of Y's (GS) by Jim Maricondo
<TR VALIGN=TOP><TD ALIGN=TOP><A HREF="ysdepro.txt">ysdepro.txt</A> <tab to=T><TD> 6834<BR><TD> Crack for Ancient Land of Y's (GS) by Jim Maricondo
</TABLE><P><TABLE WIDTH=100%><TR><TD ALIGN=RIGHT><SMALL>There are 77 files for a total of 710,386 bytes.</SMALL></TABLE>

View File

@@ -0,0 +1,423 @@
ADVANCED DEMUFFIN ver 1.1
A new version of that terrible program
Demuffin.
Written By:
The Stack
Documentation By:
The Inspector
Copyright February 8, 1983
Corrupt Computing
Advanced Demuffin is available on
THE TWILIGHT PHONE
A non-Net Works system
(313)-775-1649
If you want Corrupt Computing's line of utilities on your board,
just contact THE INSPECTOR on THE TWILIGHT PHONE. Under NO
circumstances will selling or otherwise distributing Corrupt
Computing's programs on a bulletin-board be permitted without
prior permission from either THE STACK or THE INSPECTOR.
Corrupt Computing and the Twilight Phone make NO warranties,
either expressed or implied, with respect to this manual and the
software described in this manual, its quality, performance,
merchantability, or fitness for any particular purpose. This
product is GIVEN AWAY "as is". In NO event will Corrupt Computing
or The Twilight Phone be liable for direct, indirect, incidental,
or consequential damages resulting from used of this product.
Corrupt Computing and The Twilight Phone do NOT support software
pirating, this product is for back-up, research, and educational
purposes only. (HA HA HA)
What is Advanced Demuffin? Advanced demuffin will allow you to
copy a disk that is in non-standard format to DOS 3.3 format.
It will also allow you to copy from DOS 3.3 to DOS 3.3.
To use Advanced Demuffin you should be familiar with "THE BASIC
OF KRAKING BY KRAKOWICZ". (These tips are available on apple trek
systems.) You should also have a track-sector editor like The
Inspector, Disk Fixer, Nibbles Away II, or Disk Driver.
To crack some programs a integer card or crack-rom is necessary.
Advanced Demuffin will only work on some programs.
Uses of Advanced Demuffin:
1) Advanced Demuffin is the only program that I know of, that
will allow you to copy selected tracks AND sectors from one disk
to another. 2) Advanced Demuffin's main purpose was to copy disks
from a non-standard DOS to DOS 3.3. By Copying a disk from a
non-standard format to DOS 3.3 you will NOT completely un-protect
a disk. You will merely copy the program from their DOS to DOS
3.3, any checksums, nibble counts, etc. that were in the program
will still be there. To complete the un-protection process on
most disks you will have to change a byte or two, to take out the
"checks". Occasionally you will find a disk that will not
require any changes. This will most likely will only happen with
a old disk, and/or a stupid company.
Differences between Demuffin and Advanced Demuffin: Demuffin can
only copy a disk if it has a directory. Because Advanced
Demuffin copies the disk, regardless of what data is on it, you
will not have this problem.
Here is a summary of Advanced Demuffin's options.
1) CONVERT DISK: Does the actual copying of the disk. Allows
you to change different parameters, like start track,
start sector, etc...
2) LOAD NEW RWTS MODULE: Will load an RWTS for the source
disk (the disk you are converting to DOS 3.3) from a DOS
3.3 disk.
3) LOAD NEW IOB MODULE: Will load a new interface for the
source disk's RWTS from a DOS 3.3 disk.
4) FORMAT TARGET DISK: Initializing a disk in either drive,
in DOS 3.3 format.
5) EXIT TO MONITOR: Gee, I wonder what this does? (If you
don't know, you probably should not be using Advanced
Demuffin.)
To use the options, move the "light bar" with the arrow keys.
The left arrow moves the bar up and the right arrow moves the bar
down. To execute an option, just move the bar to it and press
RETURN.
The CONVERT DISK option will do the actual converting of the
disk. To use the convert option move the light bar to "CONVERT
DISK" and press RETURN. When you access the convert option, make
sure that you already have the source RWTS in memory and have the
IOB module pointing to it. (The IOB module normally points to
$BD00.)
Advanced Demuffin will then ask you: "CHANGE DEFAULT VALUES?" If
you want to copy from track $0, sector $00 to Track $22, sector
$0F, by 1, with 1 retry and to drive two, then answer "N" for no
to this question. If you answer "Y" for yes then Advanced
Demuffin will ask you: "SECTORS PER TRACK? (13/16)" The first
digit of has to be a 1. You should then enter a "3" for a
thirteen sector disk (DOS 3.2) or a "6" for a sixteen sector disk
(DOS 3.3). If you don't know if the disk has 13 or 16 sectors
try to convert it with 16 sectors, and if you get errors on all
sectors past sector "C", then it is most probably a 13 sector
disk.
All the option "SECTORS PER TRACK" does is tell Advanced Demuffin
at what sector to change to a new track.
Then Advanced Demuffin will ask you to enter the "START TRACK",
enter the track (normally $0) in hex. You may enter half tracks,
just type a "." after you enter the track and Advanced Demuffin
will automatically tack a ".5" on the end of the track.
Then enter the start sector number in hex when Advanced Demuffin
prompts you to.
Advanced Demuffin will then ask you to enter the end track and
sector.
NOTE: The start track and sector must come before the end track
and sector. EX:
Start track: $00 Start track: $22
Start sector: $00 Start sector: $0F
End track: $22 End track: $00
End sector : $0F End sector: $00
This is fine. But this is illegal. If you enter
it this way Advanced Demuffin
will give you the message:
"BACKWARDS COPYING NOT SUPPORTED!"
After entering the track and sectors, Advanced Demuffin will ask
you what increment what you want to go by. (Usually 1) Anybody
that wants to change the increment (to anything other than one),
should already know what increment is, so I won't explain it.
You will then be asked "MAX # OF RETRIES?". You should then enter
the number of times (usually 1) you want Advanced Demuffin to try
to read/write a sector if it gets an error on it.
Then you should enter the drive to be copied to.
NOTE: The source drive must always be drive 1 because of
limitations of the IOB module.
If you specified two drives then Advanced Demuffin will prompt
you to:
"INSERT DISKS AND PRESS RETURN"
You should then insert the source in drive 1 and the target in
drive 2 and press RETURN. Advanced Demuffin will the proceed to
convert the disk to DOS 3.3.
If you specified one drive, Advanced Demuffin will ask you to:
"INSERT SOURCE DISK AND PRESS RETURN"
You should then insert the source disk and press RETURN.
Advanced Demuffin will then read 7 tracks off source and ask you
to insert the target, you should then insert the target, Advanced
Demuffin will then write those 7 tracks. It will take 5 passes to
copy the whole disk.
After the disk is copied, Advanced Demuffin will display the
message "PRESS ANY KEY TO CONTINUE". If you press 1-7 Advanced
Demuffin will then do a "screen dump to printer" in the slot of
the number that you pressed. Any other key will return you to
the main menu.
The Display
ADVANCED DEMUFFIN 1.1 - COPYRIGHT 1983
WRITTEN BY THE STACK - CORRUPT COMPUTING
========================================
TRK:
+.5:
0123456789ABCDEF0123456789ABCDEF0123
SC0:
SC1:
SC2:
SC3:
SC4:
SC5:
SC6:
SC7:
SC8:
SC9:
SCA:
SCB:
SCC:
SCD:
SCE:
SCF:
========================================
16 SC $00,$00 TO $22,$0F BY 1.0 TO DRV 2
The top 2 lines are just the title lines. Then comes the status
display. The first two lines contain the track list. Each track
number is displayed here, starting at $00 and ending at $23 (note
that the all values are displayed in HEX format, not DECIMAL).
Although the APPLE II DISK usually uses only tracks $00-$22,
occasionally some software uses track $23. For this reason,
track $23 has been included. The first line of the status
display (marked with "TRK" on the left side of the screen) is for
normal tracks. The next line is for half tracks (marked with a
"+.5"). The next line is the actual track numbers. After this is
a "map" of the disk.
After the disk map there is another display. It shows what
format the disk is in (13 or 16 sector), then it shows the start
track and sector, and the end track and sector. The next thing
on the status line is the track increment. The last thing is the
drive to copy to.
There are a number of status codes that appear in these displays.
An inverse "R" on the disk map shows a sector being read in. An
inverse "W" in the disk map shows a sector being written out to
disk. An inverse "R" or "W" on track list shows which track is
being read or written. A "." on either the disk map or the track
display shows the sector or track copied correctly.
Error codes and messages:
"R" on the track list - Some sectors on the track could not be
read.
"W" on the track list - Advanced Demuffin could not write out
some sectors on that track.
"R" on the disk map --- That sector could not be read.
"W" on the disk map --- That sector could not be written.
When Advanced Demuffin detects that the target disk is "write
protected", it will replace the title lines with this message:
DISK WRITE-PROTECTED!
PRESS "S" TO START OVER, "C" TO CONTINUE
You should then remove the write protect tab or insert another
disk. If you want Advanced Demuffin to start copying from the
start sector and track press 'S'. If you want it to continue
copying from where it is press 'C'.
What is a RWTS module? A RWTS module is the RWTS will be used to
copy the source disk. When you access the "LOAD NEW RWTS MODULE"
Advanced Demuffin will prompt you to "PAGE TO LOAD AT (MUST BE A
2 DIGIT HEX NUMBER):" You must then enter the page number of the
address that you want to load RWTS at. i.e. $B8 would load it at
$B800. Advanced Demuffin will only allow you to load the RWTS
between $20 and $BF. (Usually the RWTS is loaded at $B800.)
Advanced Demuffin will then ask you to "PLEASE TYPE THE NAME OF
THE FILE TO LOAD". You should then enter the file name. When
you press RETURN, Advanced Demuffin will ask you what drive to
load it from. You should then enter a 1 or a 2. Possible
errors:
1) NO SUCH BINARY FILE EXISTS! This message is the same
as a "FILE NOT FOUND" error.
2) PLEASE INSERT THE CORRECT DISK CORRECTLY
IN CORRECT THE DRIVE AND PRESS <RETURN>
This means that Advanced Demuffin had problems
reading your RWTS.
IOB modules: To load an IOB module, all you have to enter the
file name and the drive. What is an IOB module? An IOB module
is an interface for the source RWTS. Advanced Demuffin uses the
IOB module to set up the IOB table and jump to RWTS. The IOB
module is stored from $1400-$14FB. When Advanced Demuffin loads
in a IOB module, it reads the first sector of the file off the
track-sector list and stores it at $13FC-$14FB. When Advanced
Demuffin wants to read a sector it JSRs to the IOB module with
the phase number, sector number, and the page number stored in
the A, Y and X registers respectively. Since the source drive
always has to be drive one, Advanced Demuffin can make the IOB
module very compact. After it gets the page,track and sector
Advanced Demuffin sets up the IOB for RWTS using this
information, and JMPs to RWTS. (It jumps instead of JSRing,
because it lets the RWTS do the RTS.) Here is a list of the IOB
module that is built in to Advanced Demuffin:
*1400L
1400- 4A LSR ; Convert phase # to track #
1401- 8D 22 0F STA $0F22 ; Store track number
1404- 8C 23 0F STY $0F23 ; Store sector number
1407- 8D 27 0F STX $0F27 ; Store page number
140A- A9 01 LDA #$01
140C- 8D 20 0F STA $0F20 ; Store the drive number
140F- 8D 2a 0F STA $0F2a ; Store the read code
1412- A9 0F LDA #$0F ; With high byte of IOB
1414- A0 1E LDY #$1E ; With low byte of IOB
1416- 4C 00 BD JMP $BD00 ; Goto RWTS
1419- 00 BRK
141A- 00 BRK
Unless you want to read half tracks, you need the LSR to convert
the phases to tracks. (If you want to read half tracks, make sure
the source RWTS can read half tracks!)
Here is a list of reasons that one might need a different IOB
module:
1) If the source RWTS uses the some of the same zero page
locations as Advanced Demuffin, the IOB module would have
to swap those out before the read, and swap them back in
after the read.
2) The source RWTS resides within the text window, or over
part of Advanced Demuffin. You would then have to write an
IOB module to swap Advanced Demuffin or the text screen out
and the RWTS in. Then you JSR to the RWTS. When the RWTS
does the RTS, it will return to the IOB module. The IOB
module can then swap the text screen or Advanced Demuffin
back in.
3) The RWTS's IOB module is different from a normal IOB.
You should make sure that you JSR to the RWTS instead of JMPing
to it, so that it can move the things back to their right place.
You may also need to modify the IOB module to read half tracks.
Or if the RWTS is in a different place, you will have to change
the IOB module.
There are two ways to Demuffin a disk; the way you have to do it
with Demuffin and the way that Advanced Demuffin allows you to do
it. I will only discuss the second method. (For additional
information on Demuffin, see Pirates Harbor cracking tips.)
MISCELLANEOUS FEATURES:
To return to the menu from any point just press "ESC".
You can change the starting and ending page number of the buffer
by changing locations $1cf0 and $1cf1 (Normally a $20 and $70 are
stored in these locations). When you change these, make sure
that the start page is stored in $1cf0 and the end page is stored
in $1cf1. If you store these numbers in reverse then Advanced
Demuffin will only use a one page buffer. This is explained in
full in the Advanced Demuffin TECH-NOTES.
Differences between Advanced Demuffin ver 1.0 and ver 1.1:
All options work including LOAD RWTS MODULE & LOAD IOB MODULE.
Does not require a DOS or an RWTS to function properly,
however, if you don't have an RWTS in memory you either have
to load one with 'LOAD NEW RWTS MODULE' or change the JMP in
the IOB module to point to $1A00 instead of $BD00.
Default is to read in $7000 bytes per pass meaning that the
entire disk can be converted in 5 passes (especially useful
with only one drive.)
The buffer start, end and (meaning size, also) can easily be
changed by changing locations $13F9 (start page of buffer)
and $13FA (end page of buffer.) The defaults for these
locations are $20 and $90, respectively giving a buffer size
of $7000 bytes as mentioned above.
CTRL-Y and & will get you back into the program in case of
accidental or purposeful exit.
Will do a screen dump to the printer at the 'PRESS ANY KEY TO
CONTINUE' message that you get after the conversion is done.
At this time, typing a number from 1-7 will do a screen dump
to the specified slot in which a printer is recommended to be
in. Before printing, however, the program will print a
"CTRL-I80n" so that the output will not go to the screen
during print causing the screen to scroll up and the printout
to be all messed up, etc. Also, even though the screen will
say "PRESS ANY KEY TO CONTINUE" at the top, the printout
won't as this is the one and only modification the screen
dump routine makes to the text as it goes to the printer.
Note also that 1-7 may be typed during copy and it will be
remembered until the conversion is completed. Any other key
(besides 1-7 or ESC) will clear the 1-7 key though. (ESC at
any time should bring you back to the main menu.)
The left-arrow key <- works as a backspace-delete in inputs
allowing multiple characters such as track number inputting.
The maximum number of retries per sector may be specified if
you decide to change the default values. This number may be
from 0 (only one try - no retries) to $F (15) in which it
would it try 15 more times to read in an unsuccessfully read
sector until it got it. The default for this, although the
program does not mention it anywhere, is one retry.
If backwards copying is attempted, you will be given an error
message instead of it incorrectly copying only the first
sector.
You don't have to do the $1318 modification - The IOB module
(which is now at $1400 instead of $1300) now points to $bd00
instead of $1900 or whatever.
It asks for the "INCREMENT" when changing the default values
instead of asking "BY".
It does not print through DOS.
================================================================
If you have any questions, problems, or concerns just contact
THE INSPECTOR on THE TWILIGHT PHONE.


View File

@@ -0,0 +1,68 @@
ACTUALLY DEMUFFINING A DISK: Using Castle Wolfenstein as an
example. (I used this because it is the only thing that I that
have that wasn't cracked!)
1) Boot up Castle Wolfenstein. Before the cursor appears press
CTRL-C. The one character buffer in the keyboard will
remember it and when DOS asks for a character it will give
the CTRL-C. The CTRL-C will cause Castle Wolfenstein's hello
program to break into BASIC after it is loaded.
2) Enter the monitor with "CALL-151". Enter "4000<B800.BFFFM"
this will move MUSE's RWTS down to a "safe" area of memory.
3) Insert a "slave" disk in drive one and boot the disk with
6 CTRL-P (If your disk drive is in slot 6 of course). Press
RESET when the prompt (]) appears. This will prevent your
"hello" program from erasing MUSE's DOS.
4) Insert a disk with at least 10 free sectors on it. Save out
the RWTS with "BSAVE MUSE-RWTS,A$4000,L$800".
5) Brun Advanced Demuffin. Move the light bar to "LOAD A NEW
RWTS MODULE" and press RETURN.
6) Type the page number to load the RWTS at ($B8). Then type
the file name that you saved it under and press RETURN.
7) Move the light bar to "CONVERT DISK" and press RETURN. You
do want to change default values.
8) The disk is a thirteen sector disk, so enter a "3" for
the question "SECTORS PER TRACK? (13/16)".
9) You want to copy from track $03,sector $00 to track $22,
sector $0c. The increment is $1. (you are copying from track
$03 because you don't need MUSE's DOS.)
10) You might encounter some errors, so use "1""as the number or
retries.
11) If you have two drives in the same slot, enter a "2" for
drive to copied to.
12) If you only have one drive, enter a "1" for drive to be
copied to.
13) Insert the proper disk(s) when Advanced Demuffin prompts you.
Advanced Demuffin will then start converting the disk. After the
disk has been converted, and Advanced Demuffin displays this
message "PRESS ANY KEY TO CONTINUE", you should write down all
the sectors that read errors on them. If you have a printer, all
you have to do is press the slot number of the printer, and
Advanced Demuffin will dump the screen to the printer.
You should then re-convert the sectors that had read errors (use
at least 2-retries). If those sectors don't convert this time,
they are probably just un-written DOS 3.2 sectors.
Use Super Copy III or Master Create to copy dos on to the target
disk. You should then rename the "hello" program from ^HELLO to
HELLO.
You should then have (hopefully) a cracked copy of Castle
Wolfenstein!


View File

@@ -0,0 +1,374 @@
TECH-NOTES FOR
Advanced Demuffin 1.1
Written by
The Stack
Copyright 1983
Corrupt Computing
If you want source code for any of Corrupt Computing's line of
utilities, just contact THE INSPECTOR on THE TWILIGHT PHONE.
================================================================
ZERO PAGE LOCATIONS
$22 WNDTOP These 2 zero page locations, WNDTOP and WNDBTM,
$23 WNDBTM are used so that the character that the
character output routines in the monitor will
output characters only in the window below the
first 3 lines and above the bottom 2 lines.
The top 3 and bottom 2 lines are used for title
lines and status display. These locations
should be restored to normal upon return from
your RWTS if it uses them, although most RWTS's
don't use these reserved monitor locations.
$26 GBASL These 2 zero page locations are used by many
$27 GBASH routines throughout Advanced Demuffin, such as
the PRINT routine and the routines to display
the status codes on the disk map, but they do
not need to be saved before going to your RWTS.
Many RWTS's, including RWTS 3.3, use these
locations in several places.
$36 CSWL CSWL and CSWH should always point to the address
$37 CSWH of the current character output routine.
Advanced Demuffin sets these locations to point
to $FDF0, the standard character output
routine. Note that the outputed characters
will no longer go through DOS as there may be
no DOS in the machine. Advanced Demuffin
changes the contents of these locations to
point to $Cx00 when a number from 1-7 is
pressed during a conversion or after a
conversion is completed, where x is the number
pressed. These locations should be restored to
point to $FDF0 if your RWTS uses them in any
way. Most RWTS's, including RWTS 3.3, don't
use them at all.
$4A TEMP1 Although most RWTS's don't use these locations,
$4B TEMP2 they are used as scratch locations by Advanced
$4C TEMP3 Demuffin and are VERY IMPORTANT! Be sure and
save them if your RWTS even looks at them. The
most important location to save is $4B, which
contains the page number that the current
sector is being loaded into. Note that this is
a duplicate of the X register upon entry into
the user's IOB module at $1400.
PRE-PROGRAM NON-ZERO PAGE LOCATIONS
$200 BUF Page 2, the character input buffer, is used as a
buffer to hold the file name of the RWTS or IOB
module to be loaded. This page may be used by
your RWTS, but your RWTS may not reside in the
area between $200-$21E (unless you don't plan
on loading anything), as this portion of page 2
will be destroyed upon a load.
$3F2 RESET Advanced Demuffin sets this pointer to pnint to
$FF59. This means that whenever the RESET key
is pressed, the Apple will jump into the
monitor. If this is not desired, $12C9 (low
byte) and $12CE (high byte) may be changed to
have the RESET key go wherever you want it to
go including $801 (Advanced Demuffin entry).
$12C9 normally contains a $59 and $12CE
normally contains an $FF.
$3F5 AMPVEC Advanced Demuffin sets up these locations to
$3F8 CTYVEC jump to the Advanced Demuffin entry point
($801) when Applesoft recieved the "&" command
and when the monitor recieved the CTRL-Y
command. This provides a useful way to get
back into Advanced Demuffin after exit.
$400-$7FF Many times Advanced Demuffin displays data and
status marks on the screen by storing this data
directly into this area of memory. This
includes all marks on both the track map and
the disk map as well as numbers on the bottom
screen line, and dashes and other messages on
the 3rd and 23rd lines.
INTER-PROGRAM LOCATIONS
$800 This is the location where Advanced Demuffin is
designed to run at. This location contains an
$EA (NOP) as the byte at $800 is often replaced
by a $00. This is NOT the entry point to
Advanced Demuffin ($801 is the entry) although
if there is an $EA here it won't make any
difference if you use this as the entry.
$801 START0 This is the entry point to Advanced Demuffin 1.1
where there are two instructions, SEI and CLD,
before the actual START of Advanced Demuffin.
$803 START This is the actual start of the program which
sets CSWL and CSWH to point to the monitor
routine COUT1, sets the RESET, AMPVEC, and
CTYVEC as mentioned above (see appropriate
label), sets the full screen as a window except
for the top 3 and the bottom 2 lines, clears
the screen, puts the title at the top, the
status line at bottom, and starts off the
program by displaying the menu.
$F1E IOB This is the IOB that Advanced Demuffin uses when
it uses RWTS. The built-in IOB module (IOB33)
which is described below, as well as the
default user IOB module (at $1400) also use
this IOB. The default contents of this IOB are
described in detail below:
$F1E:01 60 IOB DFB $01,$60
$F20:01 DRIVE DFB $01
$F21:00 VOLUME DFB $00
$F22:00 TRACK DFB $00
$F23:00 SECTOR DFB $00
$F24:2F 0F DW DCT
$F26:00 DPAGL DFB $00
$F27:80 DPAG DFB $80
$F28:00 00 DFB $00,$00
$F2A:01 CODE DFB $01
$F2B:00 ERROR DFB $00
$F2C:00 60 01 DFB $00,$60,$01
$F2F:00 01 DCT DFB $00,$01
$F31:EF D8 DFB $EF,D8
Note that the slot number used by Advanced Demuffin could easily
be changed bu changing $F1F to the $x0 where x is the slot
number of the desired drive.
$F33 IOB33 This is the built-in IOB module used to write to
3.3 formatted disks. A disassembled listing of
it is included below:
$F33- IOB33 STY SECTOR ;Store sector
$F36- STX DPAG ;and page number
$F39- LSR A ;Convert phase # to track #
$F3A- STA TRACK ;and store it
$F3D- LDA DRV ;Check # of drives
$F40- STA DRIVE ;and store it as drive to write to
$F43- THERE LDA #2 ;Set command code to write
$F45- STA CODE ;and store it
$F48- JSR GORWTS ;and go to 3.3 RWTS to write it
$F4B- LDA #1 ;Restore read
$F4D- STA CODE ;command code
$F50- LDA ERROR ;Check for an error
$F53- BCC RTS4 ;Exit if none
$F55- CMP #$10 ;Write protect error?
$F57- SEC ;Keep carry set
$F58- BNE RTS4 ;Not write protect, exit w/carry set
$F5A- LDY #$27 ;Display write protected
$F5C- MOV4 LDA WPER1,Y ;error message
$F5F- STA SCLN1,Y ;and ask whether
$F62- LDA WPER2,Y ;to continue or
$F65- STA SCLN2,Y ;start over
$F68- DEY
$F69- BPL MOV4
$F6B- JSR PRINT ;Print 3 beeps
$F6E- DFB $07,$07,$87
$F71- KEY10 JSR KEYIN ;Read a key - go back to menu if esc
$F74- CMP #$C3 ;Continue?
$F76- BEQ CONTIN ;Yes, branch
$F78- CMP #$D3 ;Start over?
$F7A- BNE KEY10 ;No
$F7C- PLA ;Yes
$F7D- PLA ;Pull return address off stack
$F7E- JSR REPLNS ;Replace top 2 lines w/ title lines
$F81- JMP GOTVAL ;Starts over
$F84- CONTIN JSR REPLNS
$F87- BMI THERE ;Always taken
$13FA-$13FB These 2 bytes are unused
$13FC-$13FF These 4 bytes are reserved for the address and
the length of the IOB module when it is being
loaded. Advanced Demuffin loads the first
sector from the track/sector list of the IOB
module at $13FC. Since the first 4 bytes of
this sector contain the address and the length
of the file, those bytes reside in these
locations. Therefore, the actual IOB module
will start at $1400 (just below).
$1400 IOBM This is the user IOB module. The LOAD NEW IOB
MODULE will load a file into this area (see
above). A disassembled listing of the default
user IOB module is included in the main manual.
$1419-$14FB These bytes between the user IOB module and RWTS
3.3 are left free for an IOB module longer than
the default one. This allows an IOB module to
take up as much as $FC bytes total.
$14FC-$14FF These 4 bytes are unused.
$1500-$1CDB RWTS 3.3 resides in this area of memory. It is
just standard RWTS that has been relocated to
run at this address. Advanced Demuffin uses
the entry at $1A00.
Below are some other locations used as scratch by Advanced
Demuffin. These may be looked at by your IOB module in
determining various options about how it is to read sectors
from the source disk if desired.
$1CE0 SCVER This location contains either a $0C or a $0F
for 13 and 16 sector modes, respectively.
$1CE1 STPHS This location contains phase number to start
reading data from the disk with. It defaults
to $00. (Since it is a phase #, a $01 would
mean track .5, etc.)
$1CE2 ENPHS ENPHS is the same as STPHS except that it
contains the last phase to read data from.
$1CE3 STSEC STSEC contains the first sector within the phase
specified by STPHS that data should be read
from.
$1CE4 ENSEC ENSEC contains the last sector within the phase
specified by ENPHS that data should be read
from.
$1CE5 CRPHS This location contains the current phase that
data is being read from.
$1CE6 CRSEC This location contains the current sector that
data is being read from.
$1CE7 BGSEC BGSEC contains the sector number within the
phase specified by BGPHS (below) that data has
started being read from this pass. i.e. If you
are converting an entire 16 sector disk with
the default options and the default buffer size
($70 pages), during the first pass BGPHS and
BGSEC will both contain a $00 (phase 00, sector
00 was the start phase, sector in this pass).
During the second pass, BGPHS and BGSEC will
contain $0E and $00, respectively. (The second
pass started with track 07, sector 00 and track
07 is phase $0E).
$1CE8 BGPHS See above.
$1CE9 BYPHS This byte contains the increment in phases.
i.e. The default increment, 1.0, would be $02.
$1CEA NRETRY This byte contains the maximum number of retries
(normally $01).
$1CEB RETRY This byte is used as a counter counting down
from the maximum number of retries to $00. On
the first attempt to read a sector, RETRY will
equal NRETRY. If the carry is set upon return
from the user's IOB module, RETRY will be
decreased. If it is less than zero, a read
error will result. If not, a read will be re-
attempted. This process will continue until
the sector either reads correctly or until
RETRY is less than zero.
$1CEC DRV This location contains either a one or a two
respective to the number of drives being used.
The built-in IOB module uses this location to
determine which drive to write data to.
$1CED-$1CEF These 3 bytes are unused
$1CF0 BUFST BUFST contains the page number of the start of
the buffer. This buffer is used to store data
read off the source disk. By changing this
location and/or BUFEN (below) you can easily
change the buffer size and the location of
Advanced Demuffin's buffer. This location
normally contains a $20 meaning that the buffer
normally starts at $2000.
$1CF1 BUFEN BUFEN contains the page number of the first page
not to be included in Advanced Demuffin's
buffer (see above). i.e. If this location
contained a $90 (the default value) and BUFST
(see above) contained a $20 (the default again)
the buffer would reside from $2000 to $8FFF
(which it normally does). However, this
byte may be changed from a $90 to another
value, such as a $B8, making the buffer much
larger. In this example, your buffer would be
$9800 bytes long! This will, of course, erase
DOS when you attempt to convert the disk; but
no problem - Advanced Demuffin does not require
DOS anyway. (Not even for loading RWTS and IOB
modules!) Another use for changing this byte
the one before it is to move the buffer to a
different place. i.e. If you had a hi-res
screen on hi-res page 1 ($2000-$3FFF) that you
wanted to keep in memory, you could simply
change BUFST ($1CF0) to $40, forcing the buffer
to start at $4000 instead of $2000 - saving
your screen.
$1F00 DIRSEC This page is used as a scratch page when loading
sectors from the disk. i.e. When loading a
RWTS or an IOB module, the directory sector
containing the name of the file to load will be
read into this page. The track and sector of
the track/sector list will be found and the
track/sector list will then be loaded here.
$BD00 USRRWTS This is address JuMPed to by the default user
RWTS. You should either have an RWTS here or
the IOB module should be changed to point to a
different location. Note the $BD00 does not
necessarily have to be the start of the RWTS
when using the default user IOB module, it must
be the ENTRY POINT of the RWTS. In fact, most
RWTS's have a STARTING ADDRESS of $B800 but an
ENTRY POINT at $BD00. Keep this in mind when
you load an RWTS module from disk.
$C000 KEYBD These are the only hardware locations used by
$C010 KEYCLR Advanced Demuffin other than during the screen
dump where $Cx00 is JSRed to (where x is the
slot number).
The following monitor routines are used by Advanced Demuffin:
$F847 GBASCALC
$FB2F INIT
$FC58 HOME
$FD8E CROUT
$FDED COUT
$FDF0 COUT1
$FF59 MONITOR


View File

@@ -0,0 +1,427 @@
TECH-NOTES FOR
Advanced Demuffin 1.1
Written by
The Stack
Copyright 1983
Corrupt Computing
If you want source code for any of Corrupt Computing's line of utilities, just
contact THE INSPECTOR on THE TWILIGHT PHONE.
================================================================
ZERO PAGE LOCATIONS
$22 WNDTOP These 2 zero page locations, WNDTOP and WNDBTM,
$23 WNDBTM are used so that the character that the
character output routines in the monitor will
output characters only in the window below the
first 3 lines and above the bottom 2 lines.
The top 3 and bottom 2 lines are used for title
lines and status display. These locations
should be restored to normal upon return from
your RWTS if it uses them, although most RWTS's
don't use these reserved monitor locations.
$26 GBASL These 2 zero page locations are used by many
$27 GBASH routines throughout Advanced Demuffin, such as
the PRINT routine and the routines to display
the status codes on the disk map, but they do
not need to be saved before going to your RWTS.
Many RWTS's, including RWTS 3.3, use these
locations in several places.
$36 CSWL CSWL and CSWH should always point to the address
$37 CSWH of the current character output routine.
Advanced Demuffin sets these locations to point
to $FDF0, the standard character output
routine. Note that the outputed characters
will no longer go through DOS as there may be
no DOS in the machine. Advanced Demuffin
changes the contents of these locations to
point to $Cx00 when a number from 1-7 is
pressed during a conversion or after a
conversion is completed, where x is the number
pressed. These locations should be restored to
point to $FDF0 if your RWTS uses them in any
way. Most RWTS's, including RWTS 3.3, don't
use them at all.
$4A TEMP1 Although most RWTS's don$, use these locations,
$4B TEMP2 they are used as scratch locations by Advanced
$4C TEMP3 Demuffin and are VERY IMPORTANT! Be sure and
save them if your RWTS even looks at them. The
most important location to save is $4B, which
contains the page number that the current
sector is being loaded into. Note that this is
a duplicate of the X register upon entry into
the user's IOB module at $1400.
PRE-PROGRAM NON-ZERO PAGE LOCATIONS
$200 BUF Page 2, the character input buffer, is used as a
buffer to hold the file name of the RWTS or IOB
module to be loaded. This page may be used by
your RWTS, but your RWTS may not reside in the
area between $200-$21E (unless you don't plan
on loading anything), as this portion of page 2
will be destroyed upon a load.
$3F2 RESET Advanced Demuffin sets this pointer to pnint to
$FF59. This means that whenever the RESET key
is pressed, the Apple will jump into the
monitor. If this is not desired, $12C9 (low
byte) and $12CE (high byte) may be changed to
have the RESET key go wherever you want it to
go including $801 (Advanced Demuffin entry).
$12C9 normally contains a $59 and $12CE
normally contains an $FF.
$3F5 AMPVEC Advanced Demuffin sets up these locations to
$3F8 CTYVEC jump to the Advanced Demuffin entry point
($801) when Applesoft recieved the "&" command
and when the monitor recieved the CTRL-Y
command. This provides a useful way to get
back into Advanced Demuffin after exit.
$400-$7FF Many times Advanced Demuffin displays data and
status marks on the screen by storing this data directly into
this area of memory. This includes all marks on both the track
map and the disk map as well as numbers on the bottom screen
line, and dashes and other messages on the 3rd and 23rd lines.
INTER-PROGRAM LOCATIONS
$800 This is the location where Advanced Demuffin is
designed to run at. This location contains an
$EA (NOP) as the byte at $800 is often replaced
by a $00. This is NOT the entry point to
Advanced Demuffin ($801 is the entry) although
if there is an $EA here it won't make any
difference if you use this as the entry.
$801 START0 This is the entry point to Advanced Demuffin 1.1
where there are two instructions, SEI and CLD,
before the actual START of Advanced Demuffin.
$803 START This is the actual start of the program which
sets CSWL and CSWH to point to the monitor
routine COUT1, sets the RESET, AMPVEC, and
CTYVEC as mentioned above (see appropriate
label), sets the full screen as a window except
for the top 3 and the bottom 2 lines, clears
the screen, puts the title at the top, the
status line at bottom, and starts off the
program by displaying the menu.
$F1E IOB This is the IOB that Advanced Demuffin uses when
it uses RWTS. The built-in IOB module (IOB33)
which is described below, as well as the
default user IOB module (at $1400) also use
this IOB. The default contents of this IOB are
described in detail below:
$F1E:01 60 IOB DFB $01,$60
$F20:01 DRIVE DFB $01
$F21:00 VOLUME DFB $00
$F22:00 TRACK DFB $00
$F23:00 SECTOR DFB $00
$F24:2F 0F DW DCT
$F26:00 DPAGL DFB $00
$F27:80 DPAG DFB $80
$F28:00 00 DFB $00,$00
$F2A:01 CODE DFB $01
$F2B:00 ERROR DFB $00
$F2C:00 60 01 DFB $00,$60,$01
$F2F:00 01 DCT DFB $00,$01
$F31:EF D8 DFB $EF,D8
Note that the slot number used by Advanced Demuffin could easily be changed bu
changing $F1F to the $x0 where x is the slot number of the desired drive.
$F33 IOB33 This is the built-in IOB module used to write to
3.3 formatted disks. A disassembled listing of
it is included below:
$F33- IOB33 STY SECTOR ;Store sector
$F36- STX DPAG ;and page number
$F39- LSR A ;Convert phase # to track #
$F3A- STA TRACK ;and store it
$F3D- LDA DRV ;Check # of drives
$F40- STA DRIVE ;and store it as drive to write to
$F43- THERE LDA #2 ;Set command code to write
$F45- STA CODE ;and store it
$F48- JSR GORWTS ;and go to 3.3 RWTS to write it
$F4B- LDA #1 ;Restore read
$F4D- STA CODE ;command code
$F50- LDA ERROR ;Check for an error
$F53- BCC RTS4 ;Exit if none
$F55- CMP #$10 ;Write protect error?
$F57- SEC ;Keep carry set
$F58- BNE RTS4 ;Not write protect, exit w/carry set
$F5A- LDY #$27 ;Display write protected
$F5C- MOV4 LDA WPER1,Y ;error message
$F5F- STA SCLN1,Y ;an``xsk whether
$F62- LDA WPER2,Y ;to continue or
$F65- STA SCLN2,Y ;start over
$F68- DEY
$F69- BPL MOV4
$F6B- JSR PRINT ;Print 3 beeps
$F6E- DFB $07,$07,$87
$F71- KEY10 JSR KEYIN ;Read a key - go back to menu if esc
$F74- CMP #$C3 ;Continue?
$F76- BEQ CONTIN ;Yes, branch
$F78- CMP #$D3 ;Start over?
$F7A- BNE KEY10 ;No
$F7C- PLA ;Yes
$F7D- PLA) ;Pull return address off stack
$F7E- JSR REPLNS ;Replace top 2 lines w/ title lines
$F81- JMP GOTVAL `Ao ?xtts over
$F84- CONTIN JSR REPLNS
$F87- BMI THERE ;Always taken
$13FA-$13FB These 2 bytes are unused
$13FC-$13FF These 4 bytes are reserved for the address and
the length of the IOB module 8^sn it is being
loaded. Advanced Demuffin loads the first
sector from the track/sector list of the IOB
module at $13FC. Since the first 4 bytes of
this sector contain the address and the length
of the file, those bytes reside in these
locations. Therefore, the actual IOB module
will start at $1400 (just below).
$1400 IOBM This is the user IOB module. The LOAD NEW IOB
MODULE will load a file into thi
s area (see
above). A disassembled listing of the default
user IOB module is included in the main manual.
$1419-$14FB These bytes between the user IOB module and RWTS
3.3 are left free for an IOB module longer than
the default one. This allows an IOB module to
take up as much as $FC bytes total.
$14FC-$14FF These 4 bytes are unused.
$1500-$1CDB RWTS 3.3 resides in this area of memory. It is
just standard RWTS that has been relocated to
run at this address. Advanced Demuffin uses
the entry at $1A00.
Below are some other locations used as scratch by Advanced Demuffin. These may
be looked at by your IOB module in determining various options about how it is
to read sectors from the source disk if desired.
$1CE0 SCVER This location contains either a $0C or a $0F
for 13 and 16 sector modes, respectively.
$1CE1 STPHS This location contains phase number to start
reading data from the disk with. It defaults
to $00. (Since it is a phase #, a $01 would
mean track .5, etc.)
$1CE2 ENPHS ENPHS is the same as STPHS except that it
contains the last phase to read data from.
$1CE3 STSEC STSEC contains the first sector within the phase
specified by STPHS that data should be read
from.
$1CE4 ENSEC ENSEC contains the last sector within the phase
specified by ENPHS that data should be read
from.
$1CE5 CRPHS This location contains the current phase that
data is being read from.
$1CE6 CRSEC This location contains the current sector that
data is being read from.
$1CE7 BGSEC BGSEC contains the sector number within the
phase specified by BGPHS (below) that data has
started being read from this pass. i.e. If you
are converting an entire 16 sector disk with
the default options and the default buffer size
($70 pages), during the first pass BGPHS and
BGSEC will both contain a $00 (phase 00, sector
00 was the start phase, sector in this pass).
During the second pass, BGPHS and BGSEC will
contain $0E and $00, respectively. (The second
pass started with track 07, sector 00 and track
07 is phase $0E).
$1CE8 BGPHS See above.
$1CE9 BYPHS This byte contains the increment in phases.
i.e. The default increment, 1.0, would be $02.
$1CEA NRETRY This byte contains the maximum number of retries
(normally $01).
$1CEB RETRY This byte is used as a counter counting down
from the maximum number of retries to $00. On
the first attempt to read a sector, RETRY will
equal NRETRY. If the carry is set upon return
from the user's IOB module, RETRY will be
decreased. If it is less than zero, a read
error will result. If not, a read will be re-
attempted. This process will continue until
the sector either reads correctly or until
RETRY is less than zero.
$1CEC DRV This location contains either a one or a two
respective to the number of drives being used.
The built-in IOB module uses this location to
determine which drive to write data to.
$1CED-$1CEF These 3 bytes are unused
$1CF0 BUFST BUFST contains the page number of the start of
the buffer. This buffer is used to store data
read off the source disk. By changing this
location and/or BUFEN (below) you can easily
change the buffer size and the location of
Advanced Demuffin's buffer. This location
normally contains a $20 meaning that the buffer
normally starts at $2000.
$1CF1 BUFEN BUFEN contains the page number of the first page
not to be included in Advanced Demuffin's
buffer (see above). i.e. If this location
contained a $90 (the default value) and BUFST
(see above) contained a $20 (the default again)
the buffer would reside from $2000 to $8FFF
(which it normally does). However, this
byte may be changed from a $90 to another
value, such as a $B8, making the buffer much
larger. In this example, your buffer would be
$9800 bytes long! This will, of course, erase
DOS when you attempt to convert the disk; but
no problem - Advanced Demuffin does not require
DOS anyway. (Not even for loading RWTS and IOB
modules!) Another use for changing this byte
the one before it is to move the buffer to a
different place. i.e. If you had a hi-res
screen on hi-res page 1 ($2000-$3FFF) that you
wanted to keep in memory, you could simply
change BUFST ($1CF0) to $40, forcing the buffer
to start at $4000 instead of $2000 - saving
your screen.
$1F00 DIRSEC This page is used as a scratch page when loading
sectors from the disk. i.e. When loading a
RWTS or an IOB module, the directory sector
containing the name of the file to load will be
read into this page. The track and sector of
the track/sector list will be found and the
track/sector list will then be loaded here.
$BD00 USRRWTS This is address JuMPed to by the default user
RWTS. You should either have an RWTS here or
the IOB module should be changed to point to a
different location. Note the $BD00 does not
necessarily have to be the start of the RWTS
when using the default user IOB module, it must
be the ENTRY POINT of the RWTS. In fact, most
RWTS's have a STARTING ADDRESS of $B800 but an
ENTRY POINT at $BD00. Keep this in mind when
you load an RWTS module from disk.
$C000 KEYBD These are the only hardware locations used by
$C010 KEYCLR Advanced Demuffin other than during the screen
dump where $Cx00 is JSRed to (where x is the
slot number).
The following monitor routines are used by Advanced Demuffin:
$F847 GBASCALC
$FB2F INIT
$FC58 HOME
$FD8E CROUT
$FDED COUT
$FDF0 COUT1
$FF59 MONITOR
-------------------------------------------------------------------------------
ACTUALLY DEMUFFINING A DISK:
-------------------------------------------------------------------------------
Using Castle Wolfenstein as an example. (I used this because it is the only
thing that I that have that wasn't cracked!)
1) Boot up Castle Wolfenstein. Before the cursor appears press CTRL-C. The
one character buffer in the keyboard will remember it and when DOS asks for
a character it will give the CTRL-C. The CTRL-C will cause Castle
Wolfenstein's hello program to break into BASIC after it is loaded.
2) Enter the monitor with "CALL-151". Enter "4000<B800.BFFFM" this will move
MUSE's RWTS down to a "safe" area of memory.
3) Insert a "slave" disk in drive one and boot the disk with 6 CTRL-P (If your
disk drive is in slot 6 of course). Press RESET when the prompt (])
appears. This will prevent your "hello" program from erasing MUSE's DOS.
4) Insert a disk with at least 10 free sectors on it. Save out the RWTS with
"BSAVE MUSE-RWTS,A$4000,L$800".
5) Brun Advanced Demuffin. Move the light bar to "LOAD A NEW RWTS MODULE" and
press RETURN.
6) Type the page number to load the RWTS at ($B8). Then type the file name
that you saved it under and press RETURN.
7) Move the light bar to "CONVERT DISK" and press RETURN. You do want to
change default values.
8) The disk is a thirteen sector disk, so enter a "3" for the question "SECTORS
PER TRACK? (13/16)".
9) You want to copy from track $03,sector $00 to track $22, sector $0c. The
increment is $1. (you are copying from track $03 because you don't need
MUSE's DOS.)
10) You might encounter some errors, so use "1""as the number or retries.
11) If you have two drives in the same slot, enter a "2" for drive to copied
to.
12) If you only have one drive, enter a "1" for drive to be copied to.
13) Insert the proper disk(s) when Advanced Demuffin prompts you.
Advanced Demuffin will then start converting the disk. After the disk has been
converted, and Advanced Demuffin displays this message "PRESS ANY KEY TO
CONTINUE", you should write down all the sectors that read errors on them. If
you have a printer, all you have to do is press the slot number of the printer,
and Advanced Demuffin will dump the screen to the printer.
You should then re-convert the sectors that had read errors (use at least
2-retries). If those sectors don't convert this time, they are probably just
un-written DOS 3.2 sectors.
Use Super Copy III or Master Create to copy dos on to the target disk. You
should then rename the "hello" program from ^HELLO to HELLO.
You should then have (hopefully) a cracked copy of Castle Wolfenstein!
---------------------------------------


View File

@@ -0,0 +1,21 @@
Alien Mind Cheat - Brought to you by The Baron
----------------------------------------------
Okay, save your game on your character disk. The main data block for position one is $0004. The rest of the positions continue in block increments of 4 (i.e. position 2 is at $0008, position 3 is at $000C, etc).
Okay, find your position on the disk w/ a block editor.
Number of Cartridges: Byte $010 & $011
Energy: Byte $00A & $00B
Key Cards: Byte $008 & $009
Level: Byte $022
The way the data is stored is very odd since that if you use certain numbers, your guy will die. For example, if you use $FFFF (65535) for your energy, your man will die after one hit. Strange? I have found lower values to work. Using $4360 (17248) seems
to work. Or you could try $270F (9999). I dunno.
You must edit the values in reverse order.
Example: To make your energy 17248, take the hex equivalent, $4360 (or $43 60), take the last byte and place it before the first to get $60 43. These bytes should go at $00A and $00B, respectively.
There are only four digits allowed for key cards. If you try to edit the key cards to 17248, A.M. will take the rightmost four digits and you will see 7248.
To change the level, simply place the respective level number at byte $022.

View File

@@ -0,0 +1,53 @@
Alien Mind
From: kermit@pro-algonquin.cts.com (Fred Gotfredson)
Newsgroups: comp.sys.apple2
This patch came on my hard drive: (yes, my OLD one- OverDrive 40)
-------------------------------------------------------------------
This is the info you need to copy Alien Mind for the
Apple IIgs. It has taken me since August to work this one
out as the game uses its own operating system. In order to
use this you MUST have Copy II Plus version 8.x or later. I
have played the gameon disk 1 with the copy but have not
yet tried past level 3 (althogh I've gone past that level on
the original). All that they did were change the address
marks from D5 AA 96 to D5 AA AA. Simple huh? So to make the
copy boot up Copy II plus and go to the Sector Editorand
change the following paramaters:
Paramater New Value Result
------------------------------------------------------------
10 AA New Address Mark
12 00 Clear old one?
55 03 Do Header Check
02 40 Helps with track length
Now do a complete copy (tracks 0 - 4F). Keep track of

View File

@@ -0,0 +1,233 @@
Assorted Cracks 1
Wings of Fury, VCR Companion, CrossWord Magic 4.0,
Tetris, RoboCop, Ikari Warriors
Plus
Dream Zone
Great Western Shootout
Task Force
Hard Ball
From: Michael Kelsey
Wings of Fury, VCR Companion, CrossWord Magic 4.0, Tetris, RoboCop, Ikari
Warriors, etc. etc. I have a solution. It took many days to come across this
one.
First, you need Copy II+ 6.5 or later, or the equivalent of a Bit Copier with
a Nibble Editor and then some patience. Also, it is much easier if you have a
Sector Editor with a string or hex search mode.
If you don't have a sector editor then skip this step. If you do, go to the
mode to patch the sector editor. Change all the YES's to NO's. Copy II+ will
overlook any checksum errors this way. Next, start from track $00, sector $00
and scan for these bytes:
AC 00 AC 00
In short this consists of periods and control-@'s. Write down the track of the
occurrence. If you get a "string not found" error than this method won't work.
Next, go into the Bit Copier and set it to edit mode. For those of you who
have Copy II+ press "/" when right before the copy process begins. Type in "0B"
and <RETURN> then "02" and <RETURN>. By the way, only copy that track where the
occurrence is found. Once the drive light stop spinning on the original drive
type "f" (I think that is the command) and enter:
E7E7E7
If you see this pattern repeated many times than you have found the copy-
protection. Starting from the first E7 (and including) count skip over six
of them and press "C" when on the seventh. Now type the following:
AF F3 FC EE E7 FC EE E7 FC EE EE FC <RETURN>
Press "Q" to quit the editor mode and continuing with Copy II+ like normal.
DO NOT COPY ONTO YOUR ORIGINAL!!!!! That is a very unwise thing to do
especially if the program doesn't use exactly this protection scheme.
Now, (if you like) got to you sector editor and read from that Track and Sector
that you wrote down earlier. If your Custom Patch settings have not been changed
then read that spot. No error should occur unless a disk drive copied poorly.
Now, go back to the PATCH screen and change it to DOS 3.3 PATCHED. Escape back
to the sector editor (the place with all the numbers and characters) and write
the sector to you BACKUP disk.
Reboot, you are done. This works with many Broderbund, Epyx, and other programs
where Roland Gustaffson implemented his floppy drive routine.
If you have questions, comments, send them to mkelsey@eecs.wsu.edu
Background behind the unprotection scheme:
------------------------------------------
After picking apart the protection scheme I found the bytes that were being used
to protect the disk:
EE E7 FC EE E7 FC EE EE FC
These bytes can be shifted around and even changed to suit the purpose of the
author. Thus, this protection scheme is flexible and changes from program to
program. The Hex bytes above have almost become a standard.
When sychronizing to the disk the floppy drive uses sync FF's. These bytes have
a binary construction of so:
1111111100 1111111100 1111111100
sync FF sync FF sync FF
The copy protection searches for the E7 bytes on the drive. Once it finds a few
it begins to read the copy protection. There is one limitation to the Disk II
Floppy drives. Zero bits (any more than two consecutively) are considered
invalid. Thus, raw bytes on the disk cannot start with zero bits. This
protection scheme is implemented because those zero bits, without special
hardware, cannot be read by conventional drives reliably. Specific programs
like Essential Data Duplicator 4.9 have the capability to control the write
process of the conventional floppy drive. This also works. But not everybody
has EDD 4.9, but most have Copy II+.
Any way, here is the raw bit structure of the Copy Protection
11100111 11100111 11100111 11100111 11100111 11100111
E7 E7 E7 E7 E7 E7
Well by adding those zero bits, the bits that the drive can't read once
sychronized, the manufacturer is able to "fool" the floppy drive.
By using the AF F3 FC combination the floppy drive is forced to sychronize onto
the normal disk data and then reads like normal DOS or ProDOS.
The Copy Protection scheme jumps midway into a bit stream to catch the necessary
data. Thus, by adding one or two zero bits to the E7 byte patterns you can
obtain the EE E7 FC EE E7 FC EE EE FC data pattern.
For example:
Data read by a conventinal copier including the zero bits.
/ E7 \**/ E7 \/ E7 \*/ E7 \**/ E7 \/ E7 \*/ E7 \*/ E7 \
11101110011100111001111110011101110011100111001111110011101110011101110011111100
\ EE / \ E7 / \ FC /\ EE / \ E7 / \ FC /\ EE / \ EE /\ FC /
AF F3 FC
10101111 11110011 11111100
\ FF / \ FF /
Seeing as I didn't mention this earlier, the copy protection scheme jumps in
midway into the seventh E7 byte. I placed 1010 to make the byte noticeable to
other people and to be a filler space. At the fifth bit the drive will read the
last four bits of the AF byte and the first four bits of the F3 and get an FF
byte. The next to zero bits in F3 act to sychronize the drive. Next, the drive
skips over the invalid zero bits and then takes the last two bits of the F3 byte
and then gets the first six bits of the FC byte. This, once again, fills the
eight bit data register and the last two zero bits force the drive to sychronize.
I tried many methods of implementing this program. The first four zero bits
1010 in the AF byte were needed simply because the IIgs and //c have a different

View File

@@ -0,0 +1,238 @@
Assorted Cracks 2
From: hackett@obelix.gaul.csd.uwo.ca (Mike Hackett)
Well, I received so many requests for my GS cracks, I decided to dig out the
whole file and post it here. I hope no one minds. Anyway, here's my handy,
dandy AppleWorks DB of GS cracks - at least the ones I remembered to put in.
Many of these should allow you to transfer the program to hard disk unless
the programmers hard coded certain disk dependent stuff. Often you can fix
that by just searching through the disk and changing any references to the
disk's name to "1/" so that they will look in the right place. Other times
the programmers were just so sure that no one could break their protection
(ha!) that they made too many assumptions about where the program was to
overcome this.
Nonetheless, I think that most of these cracks are about the best solutions.
I took the trouble to check that I couldn't see a better place to put the
patch, and as you can see, many of them are simply one or two well placed
byte changes. The reason I'm pointing this out is that many of the cracks
that I've seen in Computist and on Compuserve were not very good! Most did
not even take into account hard drives, they just found _a_ way around the
protection scheme. However, most of my own cracks were done long before I
had a hard disk, and since some were done for friends, I cannot test all of
them out. If there are any problems found, or better solutions, I be glad
to hear about them.
Now, about the table: you'll need a block editor, of course. Just find the
line that contains the name of the program (for those programs with
multiple entries for the same version, you must perform all changes), and
go to that block and byte offset within that block. If there is a pair of
block/byte numbers, then that patch must be applied in two places
identically. Check that the specified search pattern is indeed there before
changing anything. If it isn't, then try to search the entire disk for that
pattern - it may be in a different place on your disk. For patterns that
are marked (NU = not unique), this searching is not possible. Finally, if
you've found the pattern alright, enter the replacement hex codes and you're
done (unless there's another entry). Despite the length of this paragraph,
it really isn't that hard.
The entries with stars ('*') beside them have their full listings at the
bottom of the list as they were too long to fit in the table form.
Of course, here are the standard disclaimers: no guarantees, no refunds.
Your versions may be different from the one I had. And, _never_ work on
your original disk. You should first make a backup, using any standard disk
copier (i.e. not a bit copier), ignoring any errors incurred, so that the
copy won't have any of the garbage from the original. Then apply the
patch(es), and if you like, copy the files onto another disk, or hard disk
if it works. If there are any problems (or confusion) just let me know by
email (faster) or by posting.
Share and enjoy...
Program Block Byte Search Replace
---------------------- -------- -------- ---------------------- --------------
4th & Inches $C5 $97 C2 (not unique) 60
Balance Of Power(1990) $40A $18D 22 2E 47 0A AF
Bard's Tale II $42E $1F A2 58 A0 B4 80 4A
BattleChess $3D8 $FF 20 DE AA 60
Beyond Zork - Fix $41 $1BF 0B 6B
Bubble Ghost $1A7 $3C Not unique code 6B
Calendar Crafter $566 $11E 22 A8 00 E1 21 60
California Games $D2 $92 20 FB 51 90 03 AD
Cavern Cobra $218 $C9 22 (nu) 60
DeluxePaint II $291 $1B3 08 C2 30 8B 0B A9 01 00 6B
Destroyer *
Draw Plus $516 $11 8B 4B AB E2 20 A9 31 60
Dungeon Master $DA $20 A9 06 00 (nu) 82 83 00
Fantavision GS $27 $12E 27 C3 20 7A 06 AD
Fast Break $00A $1E0 22 (NU) AF
Fast Break $00A $1E7 F0 (NU) 80
GraphicWriter V1.1 $1E2 $C3 A0 00 00 91 A4 A9 65 70 60
Impossible Mission II $3A6 $101 38 ED (NU) 80 11
Impossible Mission II $3A6 $FD 22 (NU) AF
Impossible Mission II $3AE $3A 22 (NU) AF (NU)
Last Ninja, The $CD $16B C2 30 9C EF C4 80 65
Mean 18 $349 $57 E2 30 D8 AF A9 00 00 6B
Mean 18 $62D $6F E2 30 D8 AF A9 00 00 6B
Music Construction Set*
Serve & Volley *
Shadowgate $76 $8D 18 FB C2 30 0B A9 21 00 18 6B
Skate Or Die $F $36 38 (NU) 6B
Space Quest $73 $20 85 F6 F4 82 E9 00
Street Sports Soccer $24 $0 20 3C 20 18 FB C2 30 EA EA EA
Superstar Ice Hockey $9 $CB E2 30 A2 05 BC 80 18
Superstar Ice Hockey $A $1F9 E2 30 AC 1B 21 80 13
Superstar Ice Hockey $B $2A 6C 6C 8F 6B 49 49
Superstar Ice Hockey $C $11A D5 00 C2 20 C8 D4
Superstar Ice Hockey $15 $E8 E2 30 A2 14 C2 30 60
Test Drive II $16E $128 08 C2 30 5A 6B
Thexder $5D9 $1C5 C2 30 8B 4B AB AA 6B
Thexder (version 3.7) $007 $05A 22 8D 0A 00 AF
Triango $203 $F5 F4 00 (not unique) 80 19
Winter Games $423 $BE AF F3 2A E1 C9 72 80 06(-AYM.GSH)
World Games $3E $1D AF F3 2A E1 C9 72 80 06 (-LDATA)
Writer's Choice Elite $523 $45 E2 20 A9 31 8D A3 9C 60
Xenocide $42,634 $1EC,EA B0 16 20 80 0A
Xenocide $43,634 $2E,12C E2 30 (NU) 80 44
Xenocide $43,634 $77,175 06 00 8F 06 46 1E
program: Chessmaster
File: /cmaster/chessmaster/cm2100
Offset $8ED7
find: D0 08
Replace: EA EA
Comment: Type space return instead of copy protect
Program: Destroyer
Block: $3F,29B
Byte: $FE,$B7
Search: 08 0B 8B C2 30 4B AB 3B 18
Replace: 8A 49 01 A8 88 88 A2 42 6B
Program: Music Construction Set
Block: $435
Byte: $1CA
Search: 20 00 BF C5 42 49 20 C2 4A
Replace: 4C 1D 22
Program: Serve & Volley
Block: $11A,2B2
Byte: $172,14D
Search: Remove .../SYSTEM.SETUP/STARTIT (I think that what this note means)
Replace: "*"'s to "1"'s
Also, to fix a bug in S&V (don't remember what it was right now) change the
file TENNIS.SYS16, relative block 324 (need Block Warden to figure that out
- don't know the absolute block numbers for this one) byte $06D, enter the
following:
AF 34 C0 E0 29 0F 8F 34
C0 E0 AF 29 C0 E0 09 C0
8F 29 C0 E0 AF 35 C0 E0
09 18 8F 35 C0 E0 EA EA
EA EA
And in relative block 484, at byte $0C4, change the A2 00 to 80 0F.
That's all for now. If there's anything missing, ask me again, I may have
forgotten to include some. I know I don't have these: Immortal, Jack
Nicklaus Golf, Dungeon Master, Alien Mind (almost! - long time ago, though),
and I don't remember the others. Oh, I also have several //e games cracked,
but they're not very organized, so if anyone wants something, ask me
individually. Thanks. BTW, if you play Pool of Radiance and don't yet have
my copier/patcher program (on AOL) - GET IT! It makes life so much easier.
Last I checked over 150+ people had downloaded the first two versions (make
sure you get the newer one if you have POR v1.1).
/==========================================================================\
| Mike Hackett | "I don't believe you, you had the whole |
| <hackett@gaul.csd.uwo.ca> | damn thing all wrong; He's not the kind |
| Honors Computer Science III | you have to wind up on Sundays." |
| University of Western Ontario | -Ian Anderson, "Wind Up" - _Agualung_ |
\==========================================================================/
Follow XENO.SYS16
Relative Byte $4DA
CE 17 00 D0 03 -> EA EA EA 80 03
That is, you NOP out the DEC instruction and make the branch to be an
unconditional branch. If you want any other cheats or hints, let me know, I've
got lots of 'em mock@madrone.eecs.ucdavis.edu (Kenrick J. Mock)
] POKE 768,128
] BSAVE THEXDER,A$300,L$1,B$522C,T$B3
That's it. Alternately, you could use a block editor to "follow" the file
THEXDER, and change relative byte $522C to $80
========= Thexder
No one has yet responded to my offer to post this cheat, but it's
so short, that I've uploaded it anyway. (I used gscii+ 2.2 to encode
it). Rocky Giovinazzo giovin@medr0.ecs.umass.edu
FiLeStArTfIlEsTaRt
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()
MTHEXDER.CHEAT AMABAAAABwfIDIACvaIAN2wJSoRtAMABAkdf
KgwBAcJAUgAEoIKAAkSOeggOkEEAUJC04VGayVGZoNEIhJXYlR3YNBicpR2bllmZ
6IicwEDsAADMjgAXkEEAiJC0EBSep5WYgwWZsFGRpFGbiUmcxArOwADMIoGA6CAK
6orO6qjuAorOtggwioLAphGVwBycn9mctFmcpdHIgwGbk9Wb5ZWavlHIgIXdi9mc
gQ3bg82cgMXYg8Gd2FGa1BSZpxmb0lWbgQWZl5WZ5dmcgAiL19WWpdHIgwGbiUmY
JoBA6CgMiFmIgUGbg8GdyV3c2lmdhBSZgQmblV2csFGI0BCbgUGa2VGbzxWZuFGI
kBCZmZWalJXZgQnbhh2YjFmcyVGdhBycgQmbgYWa19WevRGI0dib0AgIAcTCnJiu
gQXZylGduQWZu4iL6IiL6qjuJoJA6CAPP5kIgUEVlxGclNXYzVHIhBSZlRGIvJHc
jVGdkVGdhJGI1t2YvBCc5BiZyV3by9GIpdWasFmboRFIkhXZgIXZzlGZg4yal5EI
yVmdzVHIgASZ19WevBicnlmch5Wai4CbJQMA6CQQkEkOwJC0zVmcyByc1RXZg4mc
g8Gdu92YulGdiUWdxArOwADMJ4MAECgQT5UQdAAJAYkC6qzlsBlIlNWYvlHIgIXd
jFmYwV3aoRFIkhXZgIXZzlGZ0V2agUGdg4Wavx2U1ACdyREIlZXagEDIk5WYyBHI
zNXZgEGI5V2aAsjIQpQJB5LA7AAJAolCocuu7kCNyBnIpZWZkxCeAISMkpAbnrLA
pQDKiJyOh9Gb0BCZ4VGayVGZkEGLwATMMxCMsEDJ1QiQjJjMkQFLiMjQKoHA5Cgb
5ADNxwiNAgjM4pwqnrLApQDKiJyO2F2c0BSZ4VGayVGZkEGLwATMMxCMsEDJ1QiQ
jJjMkQFLiMjQK4NAXCggkEkOZJC0yV3bpRGIgs2cgMXa39mbwVHI0FGZuQWZl5iL
vpmbiESexArOwADMKQOAACAjLIAAYNA6wQD0jjSykEEKLnSKWqjMpgFKBprOxqDJ
AAAAAAwtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AQn)
=============
Prince of Persia 3.5" deprotect:
Block: 7
Byte: $16
From: $90 (bcc)
To: $80 (bra)
Block: $A
Byte: $8C
From: $18 (clc)
To: $38 (sec)
Reader Rabbit GS
I. 1. Go to Basic
2. type prefix /reader.rabbit
3. type bload misc.rtns
4. type call -151 ( gets you into Apple Monitor with * prompt)
5. type 6003:2
6. type control-C
7. press return
8. type bsave misc.rtns
9. type bye
II. 1. create a new folder, call it whatever you like.
2. drag all files from your RRGS disk into the folder.
to run program, double-click on reader.system. There you go!

View File

@@ -0,0 +1,26 @@
Bard's Tale III Code Wheel crack
Hi All
I would like to dedicat all the funs of Apple ][ software I know to
the Apple fans. Including cracks, unlimited lives modification and
others.
The first is the Bard's Tale III Code Wheel crack.
Use Copy ][ Plus or similar tools to modify
SIDE 2 ( character disk )

View File

@@ -0,0 +1,151 @@
Bard's Tale I and II GS character editor
From: florpch@jhunix.hcf.jhu.edu (Lawrence S Lee)
As requested, the Bard's Tale I and II GS character editor.
It's self-explanatory, but if you want to edit BTII GS characters, keep in
mind that
a) gold and experience points are actually _reversed_ from what you see (ie.
the reading for gold is actually experience, and vice versa)
b) you can't really edit the items, because they're not the same as the
bard's tale I. However, you CAN use Prosel to edit the INVENTORY file, and
change _everything_ to FF's. That gives you an unlimited supply of
everything in Garth's Equipment shoppe
c) this program doesn't really _save_ the info to disk for some reason. I'm
too lazy to change itmyself, but when you save, the actual save command gets
printed to my _screen_. If that happens to you, just copy down what you see
(something like "bsave <path>/characters, t$ea, a$2000) and when you quit
the program, type that string in immediately. Then your info will be saved
to disk.
d) caution, don't make your spell- or hit-points the maximum (ie. 9999)
because if you do, and you get promoted by the review board, they'll cycle
aroud back to ZERO!
Enjoy...
Binscii'd with GSCII+ 2.3.1
-----8<-----
FiLeStArTfIlEsTaRt
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()
IBT2gs.fix AIh)AAAABw)4LIACu(MAOHhFRQjrAIh)AgKy
khADxQKA4IjMqAAOA4GCQTCR0gy56qTKiQCRjIFU6IyMocuupQjMHBwOAgHCEJMu
owkQQnSQBhi4yocKIbTNBhi4pEDyIQGAGCggoUSSskCOoUyUskCOoQiTpEzMysqO
AATMMiAe6oDATJrOyJWd0V3bl5WaVCwcAYJCijilzMDKjncKkEEKLnSKxgsMBprO
xqDJI4LABCAoxANWyETwZpDOKnF0uITMwANN4EjyqrrOkEEKInFLxwSMAsTKqiQ3
nrLApgDKYpzOoIO02ETy0gzMCqTKB5rO6qDJI4PAtCAtQTSQhJyzB1sIQHNJionI
kEExocO0xkMWpEjNJQAAxCgvJQBA6AAyyqjOhR3U1Rnc6AAcAIdCQTSQ6IiIQjVg
iHcMzMDKykcK6IzxQTSQITSQ90jICqjIJMHAwCA3wUTMxIqOkEkOgIC0lhGdlNFI
lJ3YCBCdkJXYgM3J2FGVuJXZm9GIydEI0FWZzVmbiAycJIKAwCg5wUTMzkrOxwCN
xIqOEqDMoNkIhJXYlR3YkBicrNXasNHIgQ3b7IiOAQSQwng0QPFABhS56kCJDJCh
yFGa0NWYgIXZzlGZkBya2lmcioTZkE0OQTkOBhS5AkCJ6rAAEpLACJCJh9GTDBCZ
yFGa0NWYzJXZkQHLsEURyQSYwADMiMHLsIyUEJCZK8AA6EAByqjOz9mUyVGdKUDA
BGgDwANWxMTwZFoOBDD06UTMiDdQKjFK4ITMInFy5EDOAkiMYoQTG3aAB5cQ3ED0
ZRMMwED0BpDMAAD0iowbB1aARHUz1UjMk4ExpgFKk4E0pgFKocOyxkcQpgjMKgHA
CGALYxSWK8IAXGgN6orOQjVgxEMM6qTNwEDwAsTKApArprbAgICKkjsIpgFKpIDL
gkiIk4kIpgFKIDwOBokC1AsuYlCM2EDygkiIk4kIIjFKpYTMAIoOUpA66obAxAsu
ikCOpMFKlZXY1AsIikCOpEFK0lWdTAgIB41CyIjoiQoOhh2QjFmcyVGd15GIlJWb
iojckE0OINkOQLVQBhS5AkCJotgOkEUAogO0sQSQ6kSMkEUri8M0ELSYQTSQmjy5
kEEKzkcKAkiMytAaB1aAiANJELyUkQkuTJkIlZXYoNEIhJXYlR3YsMncFRCdhxSQ
wIDJiADMLYIAtGAfQTSQiElI6cJxyEjoiorOllnY6IiLAqTiL4JAtGghBh0QwEtU
INkzPLVQEHzMwUzMLQMAtGAkINEKQLVQB1MMPHNJiAjIO5cKDhCJSFESiAdKzQsI
AATNaug36oTAFJrOtFGel5WaoNGIhJXYlR3Y1DgcBQ6CTFkQDBdRSFESyEjy4gMO
ykTMMsBABFgriANJBqjIyANWzEMMBpTMBBNJkjMJoIOKTFkQYhcRAkSK4yQO6IYA
M90RQTCR6QSQQTSQ6IiIQjVgBbzMAcDNCzQWkEUAkEE0oQOyChi4FNVQpgFyCqTK
YVkOBBNJvBAJBwMDMZFTEJM0owkQTFkQzgcRAkiMWzglQhUAEJM0owkQTFkQ0gcR
6kCOE50QEJM0owkQTFkQ1gcRAkCMgzAvQ1UAEJM0owkQTFkQ1gcR6kiMQLVTCRkw
ChCTFNVQ0UDycDQKBoODQPVTChi4FNVQ0YDyNpTKiD9QBJEKIX0UpUjNMwPANFA9
iDdTBJEKIX0UpYjNX1kOoIO0TFkQ2gcRAkyN(3gF6oTAEJrOwNXa5FGboNGIhJXY
lR3YwAgcCgQDiqzl6qDNh5kI6UWbk4kIINEKpIVQN4EA6KgEvdkI6QGbPdkIkQET
iorOwhXRioDIkgVRNsHA6KAHlxkIsVmdiAiOMZFTiorO0lGS6AycIJCI6qDUuNkI
uRHZiAiOE50QN8JA6KgJh1kIjl2ZiAiO6AVTgIiulJFIpFWbulmbgozZS1kINMMA
6KAMwNlIsxWZT1ycjJ3bNJiO6qzUpgDwvNkI6ombD1kINMOA6KgOpgDwh1kI6k2Z
N1kIArrOikCO6l2VioDZAcVTE1g)iorAz9GUzV2cvl2ciMnbiorOpVXUAICdO5QF
6ojAVJrOyV2clNHIjVGbvlGdFBgbCglDzIjoiorOwlHVsBSZ0RXZgIXZgY2b0RXY
ilmclRXdvRHIoNGIn5WYioTZWBwOCImDQTSQpgiIwqjIwYTMOYGAtKAbQTSQi4kI
1cDx2BAMCYnDkEUrHJC04QsIAAjMA6ghB1qAiANJELSRwMDOOYJAtKgiQTSQiwkI
5gDxmCAMCQpDkEUrIJC05QsIAADMe6gtB1qAiANJELyQwETOOYMAtKAqQTSQi0kI
ykDxWDAMCIrDkEUrSJC05QsIAAzM86w5B1qAiANJELyUwATM4DAMCYsDkEUrQJC0
xQsIwITMP4AAtKA0QTSQiElIQjlz2UTMxMDxXAAMCo9DwYzqkAAMCQ(D6ojOh5ks
AUWbu)gQyIqAMqzM2gTyEqDOl5kIuBydl1WY7IiOAQSQ4)AXYFoABDD06UTMBJUu
IX0UywCW6UTNECggDIwDoQiTBh0QQniU6IiIQjVgjHcMkEEKZpTKoYO0Bhi6YxCJ
AkSKM8ApZ16AmD9zhJCKNniIQHdWigi5pIieQnFxzkcWPDgMDYxDoQiTBh0QQniU
oQiTBh0QIniUZhy55qTKTFkQYhcRsETyxgcWAgjMg8g26I4AzQzqyDAMDoyD6ojO
vdksvQGbwhXZpJXZj5WZKAQZDQDEQTSQvdmIiQGbQnlO6AjM0gzqjAAMD4DEQTSQ
4VmIyVGcuVWaiU2YQnlOAYzMIBBRyI6AMqzM2gTy6qDOl5kIiAyd7QSQiQoO7IiO
AQSQSBxYkE0AokO0wAjIwADMwADMwADMILCMsQSQpITMQgIABOAXwANWxETwClrO
FNVQInFylzCWooOKsQSQxgMWpEDLTCQKDYGErqjgwMDNQALA6MAcyqjO2VGTvwWZ
0lGaj9yck52bpRXaA42b6BRykE0AsJC0lZXZ6ICbzAdWrqjMwQTOQEOABNAhiANJ
0lGa6Iyc0AdWrqDOwQTOQ4PABNgjiANJu92Y0lGZu9WaZpjIwUD05sqOAADNYGhH
kE0AtJC0pdWYwByYul2biMHdQnlO6ITN0kzqDBAMDIaEQTSQlJnIpFWbulmbtByZ
pdWYwByYul2biMHdQnlOAQTNsGBZyI6AMqzM2gTy6qDOl5kIiAyd7QSQiQoO7IiO
AQSQ2GRhQj1ABhS56kCJRjVrY5cM1Yzz1MTNQjFx1UjNAUzMAHBsCl7AFNVQskFy
ysMW6YTNBJUuIX0UxgcWJjFLYhy01IzyKniN2UjMRQMAtOgyzAdWZRsM0MD05sqO
AAjNUHRz0s6AAAzMeHh46ozATJrOsVGcsBCblZXZAMHboLRCyI6AMqzM2gTy6qDO
wNlIsxWZsNGIzNXYoAyPNN0U6kyVAsjIyLRJkE0AlIC06IyL2EDsZpDM6AD0QjVg
0EcMS8DAtOA)QTSQigi6NN0UsIyVxwCWZRcKAgF0GIhT6IIBZZcrwEDxAADMQIRZ
Z1KBEHD0QTSQvNnIlNmcyVmc8BgIEohEQnVrBRsMiANJu92YyVnaiIXZSMJAtSAJ
zAdWkEExtJC0pdWYhl2YAIibuIBqZ1KBETD0QTSQpdnIyFmeAICZ4IxzyIKBMqzM
2gTy6qDOl5kIiAyd7QSQiQoOlxGIsVmd7IiOAQSQCJh8QjFBBhS56kCJPjVro48N
xENWkEUzi8c0pICMQjFxIAwNEw0EBJUuIX0UIPjNYxSW0sqOAAzMWNBH6oDBQJrO
zN3bzNXZu9WazAwcEA2EuqzlYFoOBDD0BqTNwAdWyITwTMFAHSga6QSQKjllIPTM
iqTMygcWQrlOyoMWZh8MAEDy0Nhcj3KBkEEK6ScKigS6iACIoQOyskiWikyM7ICI
TUJA6SgfBhC6igMJgACIgACIgACIgACIxwiI7kCMyIqOAorOIOhnZJIBAgFLSOhv
YFIBBDD0TpzNYhSJiDdKBJEKIX0UIDDOyoMWXDQKEw5EoUSSQnCWChi4FNVQxgDy
KjFyAkiMmOh7xIKBYhcN3YpO6qDMxgMWiojIBAwOEALFlMVrpgFKEHD0lJiuAsjI
6SBFT1KBYhSJyAdKioLx7ICeU8CAtSAxoUyURnCWT5cMYhSJy8cKioLx7ICIUkEA
6SgzigS6iACIoQOyoUSSpkCWpMDLAIoOYTRayIKBWqzM6AzN5Iiu1FlOgQXa6sjI
QTSQrMiIDCgIEIOF2EDsYpDMoUO0pQSQG3qOxQMWwQjMUAJAtSA75ANWzQDxoCAM
EYPFzIjo3YpOMqDM2gTyYpDOJjF09CQMFAAF1Ejo6gFyzcjliQoOBtjIYDAJFoAF
lDdWkEEKtqTKwEdWPnlz3ITMQnFx6DAMFQBFBJUuIX0UIDDOyoMW6ADLBJUuIX0U
IHDOyoMWAkFLeUBBxsaBwcTMVIBA6UAKyqjOlRXSAMXbyUBSUNYBjJ3bMxCaw1WY
yJELkF2bvd3csQmcvh2UgQncvd3UsQmcnFGRyV2ZhdFLBBicAUGe8UxgINYBixWY
kJXYh1ELsU2YhR3UsYmZjVnQlx2aUxicld3bTBicllGasQGbhVGTlhGdBBicv1mc
2CgcFYUFoN0gulWYh1EIswWahN2UgUGbtJXQsI3bhxGUgUGdtJXQsI3bi9mUsMXZ
sVGSoDQbFAVFlx0goRXYgIXZvx2RzVmdhdEL05Wd0VGbNxyck5WYpx2bIxibwJXY
sZELlRXdWoBADWgWoRXTTBicy92dNxCZyhGdoNFIsVWaNxCZyhGdoNEIulWY01EL
gIHahN2UAUGbkZxSTNYB11WYpFmcnZEICxibjFmczJXZ2sFICxSXkJXYvd3csQmc
ylmRIBSZuJ3bWwHADWgbnlGT3RHak5WY01ELgIHanFGRyV2Z01ELgIHasVGSNxSb
yhGdsdEIlZ3b0CwcFgnF010ggIHalhXQ01ELgIHajFWTNxSZoRncQBic0FGbPxSZ
lJ3ZnZEIMxibnsWYMByclJXeWYOADWggph2UkxWZpJFIscmby9GRSByan5WapZEL
zdibsZEIlRXdhtELnwWZBBycAUGeMeRFCNYBv9GbBBCZsUGe5FGRhxmYsUGZph2U
kxWZ0NFImZWYsVELDBiZh9GbHBwaFY5Fhh0git2dkFGbBxSZ01GZ3NFIkJ3bkFEL
gQXbph2UkxWZkFELgQXbnFGRyV2ZXwHADWAotRWQIBCdtxWZkFELgQXbvx2RzVmd
kFELgQXbjFWTCxSZv9mcQxSblJXdhxmYAUGZqehrFNYBy9GeuF2dBxCZnkGbDByc
wJXYsQXZnFWTgMWa19WTsgGdjVHToN3asVWaeDAZFQ7Fpd0g05WYnZEIBxib01GZ
oNEIulWYkFELgQXbhN2UsUGbtRWQQBCd0FGbQAQZF4LGyJ0glNWYgMncdRzWyFEL
oN3YsVWaQxCZlJXdoNFIsVWaNxCZldWY0NFImZWYYMEADWAyyF2V0NFImZWYoRFL
mVWahREIld2ZTxicsV3bh1EIsU2Y0l2VyVGa0NFImZWYYgHADWg0y92UyV2YhR3c
sYmZvd3UgQmcgY2brFGUlhELgwWYyFGSHxCc0xWYgM3J1xmRAUGdcjxqGNYBz9mc
IBCduJ3btRELgQmbvd3UsQmcu1GRTBCZllGasQGbu1GREBCZndWYAIXZmjh2ENYB
k5WblhEIs0Gbs92Rg0WZudmRpRFLuFGdnZEIDxibq52bzJXdmFGdPAgZFAfGyF0g
zdyYhhEIl1WbTxicmFGdvBiZMBiZsI3b39GUzJXZmFGdNxiZyV3bsJmblRWYZ8DA
DWg(hJHRu92Zph2ckxWZtRELgQmbhxGUsUGdyF2Vvx2ZzVmdvxELoVmctxWZZQHA
DaABhJHRu92ZuF2dLxCZsVWagM3Jt92QzFGcTxyclVGcvJGZzR3bsZELl1WYvhEI
A4mcOkRqUNoB0VncyRGas0WdpB3U0lmc1JHZQxSblBXavBycQBiZs4WYulmUvByZ
QBiZld3bcDgcGgRGlR0goRXYulmcZxyZyFmYzFmcllGasQGblB3UyR3YNBSZlNWY
hRELTByZu9GdTAQZGIiGyF0gzdyY5VEIPxSZlJ3ZuF2dTxCZylGcoRXatxWZyREL
vdWYGBibs42ZnFWTGBSZA42ZsohRUNoBs9mcSBCbn5WayRFLsx2b0NFImZWYu9EL
ggXe5V2SyNEL0NXegwWYvd3UAQmc2oBeTNoBu9GdsJWZlRWYyRFLlZXYlhGbs0Gb
hVGRggGdnFGRyV2Zv1ELvdmbnZEIrCgbGAkGpx0ggg2YnlmRFxibsUWezFWTyVGd
ltEIXxSeXpXak5WYpNFLyZHbxNFIyFWdfDQZGokGpN1gyZHbpNEIsNmcTxSZ2xWa
UBichlmcscmbvhGVGBics42Zkx2Th1EIGBibA42ZUpR)TNoBjVGclJHduNFIlJXY
swCLswCLswCLAwCLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AULS
--
Larry Lee |
florpch@jhunix.hcf.jhu.edu | I beat up your honor student.
florpch@jhuvms.hcf.jhu.edu | And I liked it, too.
llee@gnh-starport.cts.com |

View File

@@ -0,0 +1,29 @@
Deprotect for Battle Chess
> I'd like to put Battle Chess on my Hard drive, but I tried copying all
> files to a folder, and it does not work.
>
> Is there any way to make this program Hard drive installable?
Except for needing to supply information from the manual at the
start, BC is not copy-protected. A good defeat for the protection (one
of several) was supplied by Sky Phantom in Computist #73.
You copy the diskette and use a block editor to change a byte. You
want to find 20 90 35 20 E0 32 20 DE AA 60, and change _20_ DE AA to
_AD_ DE AA. Probably, you will find the byte to change at byte location
$0FF in Block $3D8 of your copy.
A method for placing BC on hard disk was described by Robin
Locksley in Computist #86; however, it is supposed to work for GS/OS
5.04. It does not work for System 6.0.1. (The game crashes.)
So far, the closest thing to "installing" the game on a System 6
hard disk is to copy the files to a folder. To run the game, you copy
the folder contents to /RAM5 and boot /RAM5.
Rubywand

View File

@@ -0,0 +1,89 @@
Bubble Ghost from Accolade
REQUIREMENTS:
512k Apple//GS
3.5" Disk copier
3.5" Disk editor
To remove the annoying "What level is this?" question (pirate protection)
make the follow these easy steps:
1. Make a copy of the Bubble Ghost game disk
2. Make the following edit to the copy only
(rel block 78, rel bytes $9B74, $9B77, $9BA2 for Block Warden)
BLK BYTE FROM TO
------------------------------------
$17A $174 AD 00 00 9C 00 00
$177 F0 2E 80 2E
$1A2 22 00 00 00 AF 00 00 00
3. Write the block back to the copy
4. Play off the newly deprotected copy
Once again, the whole requestor screen/routine is totaly bypassed! However the
program was not hard disk compatible! I then set out fix this little problem.
All files were being loaded like this: /Bubble/WAVE. I thought I could use
the ProDOS 16 "1/" to make the program accept the current device. I now had to
change all the "/Bubble" to something, so I came up with "1/Ghost" so Bubble
Ghost will load ALL needed files off the current volume in the subdirectory
GHOST. Use a copy of Bubble Ghost for the following steps:
Make the edit From "/Bubble" (2F 42 75 62 62 6C 65 in hex)
To "1/Ghost" (31 2F 47 68 6F 73 74 in hex)
at ALL the following locations:
Any block editor Block Warden ([F]ollow /BUBBLE/BUBBLE.SYS16)
Block Byte Rel Block Rel Bytes
---------------------------------------------------
$129 $9C 47 $5C9C
$B8 $5CB8
$CA $5CCA
$171 $0F 67 $840F
$2B $842B
$87 $8487
$9F $849F
$B7 $84B7
$CF $84CF
$E7 $84E7
$FF $84FF
$172 $143 68 $8743
$158 $8758
Now get out a blank disk and format it with a name something like BUBBLE.GHOST
or what ever. At this point I DELETED all unneeded files like the FINDER.DATA
files, P8 in the system subdirectory, and FINDER.ICONS in the icons
subdirectory.
Copy the PRODOS file and the SYSTEM and ICONS subdirectories to the new disk.
Copy BUBBLE.SYS16 to the new disk.
CREATE a new subdirectory called GHOST on the new disk.
Copy the WAVE and GHOST.SCR files into the new GHOST subdirectory.
Copy the DESSINS and SONS subdirectories into the new GHOST subdirectory.
A tree directory (other than PRODOS, SYSTEM and ICONS) would look something like this:
File Type
---------------------------------
BUBBLE.SYS16 S16
/GHOST DIR
WAVE BIN
GHOST.SCR TXT
/DESSINS DIR
GHOSTGS.CGS S16
GS1.CGS S16
GS2.CGS S16
GS3.CGS S16
GS4.CGS S16
GS5.CGS S16
GS6.CGS S16
/SONS DIR
LESSONS BIN
Now to upload Bubble Ghost to your hard drive use COPY ][+, the finder, or
other file by file copier and copy BUBBLE.SYS16 and GHOST. The copy program
will copy all this files and subdirectories in GHOST. Then copy the GENE.ICONS
to your volume/ICONS subdirectory. To play the game simply luanch BUBBLE.SYS16