707 lines
55 KiB
Plaintext
707 lines
55 KiB
Plaintext
******************************************************************
|
|
* *
|
|
* MAXFILES Command Handler *
|
|
* *
|
|
*----------------------------------------------------------------*
|
|
* *
|
|
* The MAXFILES command is used to define the maximum number *
|
|
* of files that can be opened at one time (1 - 16). A default *
|
|
* value of 3 is used for cold starts (i.e. when the disk is *
|
|
* booted) or when the FP or INT commands are issued. This value *
|
|
* can be changed by altering the contents of MAXDFLT ($AAB1). *
|
|
* A diagram representing the structure of the DOS buffers *
|
|
* is given at the end of this listing. Note that 595 bytes are *
|
|
* reserved for each file and that a DOS buffer is composed of a *
|
|
* number of smaller buffers: data sector buffer, track/sector *
|
|
* list buffer, file name buffer and chain pointers buffer. The *
|
|
* first six bytes of the chain pointers buffer point to the *
|
|
* different sections of a given file buffer. The last two bytes *
|
|
* in the chain pointers buffer provide a link to the name buffer *
|
|
* of the next active file. If there are no more buffers in the *
|
|
* DOS buffer chain, the last two bytes of the last chain pointer *
|
|
* buffer are zeroed out. Similarly, if A DOS buffer is not *
|
|
* being used, the first byte in its filename buffer is $00. *
|
|
* Note that the addr of the 1rst DOS buffer at its filename *
|
|
* field (ADOSFNB1) is a constant because DOS buffers are built *
|
|
* from higher memory downward. (I.e. DOS buffer 1 is built 1rst *
|
|
* and occupies the highest memory location whereas DOS buffer *
|
|
* 16 is built last & occupies the lowest memory location.) The *
|
|
* highest numbered DOS buffer (i.e. the lowest in memory) is *
|
|
* always assigned first. *
|
|
* MAXFILES cannot normally be used successfully from an exec*
|
|
* file. Although the command is indeed executed, the computer *
|
|
* is inflicted with a terminal case of amnesia. Disorientation *
|
|
* occurs because MAXFILES shuts off the exec flag & CLOSEALL *
|
|
* subsequently releases the exec buffer. However, both *
|
|
* debilitating events can be prevented simply by NOPing out the *
|
|
* STA EXECFLAG instruction at $A253. The MAXFILES command *
|
|
* destroys Integer programs and messes up Applesoft strings. *
|
|
* This occurs because MEMSIZ & FRETOP (Applesoft) or HIMEM & *
|
|
* INTPGMST (Integer) are reset. Under special circumstances, *
|
|
* you can prevent some of these problems by placing a premature *
|
|
* "RTS" instruction in the ZLNK2NXT ($A82D) routine. You can *
|
|
* also issue a MAXFILES command from a running Applesoft program *
|
|
* if it is executed before any strings are defined or other files*
|
|
* are opened. *
|
|
* Programmers are often hard pressed to find a safe place *
|
|
* where basic won't write over their custom machine language *
|
|
* routines. Short routines are commonly put in page 3 or in the *
|
|
* tail end of the input buffer if little input is expected. A *
|
|
* few programmers even take great pains to write relocatable *
|
|
* routines that can be moved around at will or hidden in an *
|
|
* Applesoft program. However, the area between DOS & its buffers*
|
|
* represents a sanctuary for machine language programs. Although*
|
|
* this region is normally only seven bytes long, it can be *
|
|
* enlarged by fooling DOS into building its buffers at a lower *
|
|
* location. The procedure is as follows: *
|
|
* 1) load ADOSFNBF1 with a value equal to: *
|
|
* ADOSFNB1 - (L$ + $26) (where ADOSFNB1 = $9D00, *
|
|
* and L$ = hex length of program to be BLOADed. *
|
|
* $26 (dec 38) represents the bytes that normally *
|
|
* occur between the start of a DOS buffer & the 1rst *
|
|
* byte of its filename field or, in decimal notation: *
|
|
* POKE 40192, 40192 - (L# + #38). *
|
|
* 2) BLOAD your program at: A$ = ADOSFNB1 - L$, or in *
|
|
* decimal notation: A = 40192 - L#. *
|
|
* 3) call the cold start routine ($3D2), MAXFILES, FP *
|
|
* or INT to rebuild the DOS buffers. *
|
|
* Greeting programs designed to accommodate Applesoft *
|
|
* editing programs often use this technique to install the *
|
|
* editor program between DOS and its buffers. (If you are *
|
|
* writing commercial (nonturnkey) assembly language programs *
|
|
* that are designed to run on different-sized machines or *
|
|
* accommadate an altered version of DOS, note the last two *
|
|
* paragraphs at the end of this disassembly. These describe how *
|
|
* to find moved DOS buffers from an assembly language program *
|
|
* that only accesses DOS via indirect addressing.) *
|
|
* Inspection of the raw data in a DOS buffer can often *
|
|
* reveal protection techniques embedded in a program or its file *
|
|
* description (ex. non-listable programs, programs with file *
|
|
* names containing back spaces or other illegal control *
|
|
* characters, driver programs made "user unloadable" through the *
|
|
* use of illegal T/S list sector values, etc.). (See the *
|
|
* preamble given with the disassembly of the catalog command for *
|
|
* an alternate method of inspecting file descriptions. *
|
|
* *
|
|
******************************************************************
|
|
|
|
|
|
* Execution pattern:
|
|
* - Make sure that the EXEC mode is turned off.
|
|
* - Close all files.
|
|
* - Save the MAXFILES argument in the main variables table
|
|
* (MXFILVAL, $A7D4).
|
|
* - Build the indicated number of DOS buffers.
|
|
* - Check which basic is active and reset the Applesoft
|
|
* (MEMSIZ, $73-$74 & FRETOP, $6F-$70) or Integer (HIMEM,
|
|
* $4C-$4B & INTPGMST, $CA-$CB) zero-page pointers.
|
|
|
|
|
|
* On entry:
|
|
* - A5L ($44) contains the numeric argument that was issued
|
|
* with the MAXFILES command. The argument was previously
|
|
* screened to insure that it was between 1 and 16.
|
|
* Screening was done via a section ($A0AA - $A0C7) in the
|
|
* command parsing and processing routines.
|
|
|
|
|
|
(A251)
|
|
CMDMXFIL LDA #0 ;Shut off the exec flag.
|
|
STA EXECFLAG
|
|
LDA A5L ;Get argument issued with MAXFILES
|
|
(A258) PHA ;cmd and save it on the stk.
|
|
|
|
(A259) JSR CLOSEALL
|
|
|
|
* Close all files.
|
|
(A316)
|
|
CLOSEALL JSR GETNBF1
|
|
|
|
* Put address of the 1rst DOS name buffer
|
|
* (chain) in the A3L/H pointer.
|
|
(A792)
|
|
GETFNBF1 LDA ADOSFNB1 ;First link to chain of DOS buffers
|
|
LDA ADOSFNB1+1 ;(ie. pt to 1rst filename buffer 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 back in (a).
|
|
GETNXRTN RTS
|
|
(A7A9)
|
|
|
|
(A319) BNE CKIFEXEC ;ALWAYS.
|
|
|
|
(A31B)
|
|
CHKNXBUF 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 chain buffer.
|
|
LDA (A3L),Y
|
|
BEQ GETNXRTN ;If hi byte is 0, the 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 ;Condition z-flag in relation to hi byte.
|
|
GETNXRTN RTS
|
|
(A7A9)
|
|
|
|
(A31E) BEQ CLOSERTS ;Link zeroed out, so now all files closed.
|
|
(A320) ;Exit CLOSEALL via this route.
|
|
CKIFEXEC JSR CKEXCBUF
|
|
|
|
* Check if current filename buffer
|
|
* belongs to an exec file.
|
|
(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, now chk hi bytes.
|
|
CMP A3L+1
|
|
BEQ CKEXCRTN ;Exec buffer = current buffer.
|
|
NOTEXCBF DEX ;Not EXECing, there4 reduce (x) to make sure z-flag off.
|
|
(A7C2) ;(P.S. (x) was orig conditioned to a large non-zero
|
|
;value on entry to GETFNBF1. There4, if now DEX then
|
|
(A7C3) ;can be sure z-flag will be off.)
|
|
CKEXCRTN RTS ;If execing, return with z-flag on.
|
|
|
|
(A323) BEQ CHKNXBUF ;EXEC WAS 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 to exec (ie. would
|
|
;be like burying ourselves alive)!!!
|
|
(A325) JSR GETFNBY1 ;Get the first byte in the DOS name buffer.
|
|
|
|
* Get first byte from 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.
|
|
|
|
(A328) BEQ CHKNXBUF ;This one is already closed, so go back
|
|
;to close rest of files.
|
|
(A32A) JSR CLOSEONE ;Close the open file.
|
|
|
|
(A2FC)
|
|
CLOSEONE JSR CKEXCBUF
|
|
|
|
* Check if current filename buffer
|
|
* belongs to an exec file.
|
|
(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.
|
|
BEQ CKEXCRTN ;Exec buffer = current buffer.
|
|
NOTEXCBF DEX ;Not EXECing, so DEX to make sure z-flag
|
|
(A7C2) ;is off. (P.S. (x) was orig conditioned
|
|
;to a large non-zero val on entry to
|
|
;GETFNBF1. There4, if now DEX then
|
|
(A7C3) ;can be sure z-flag will be off.)
|
|
CKEXCRTN RTS ;If execing, return with z-flag on.
|
|
|
|
(A2FF) BNE FREEBUFF ;ALWAYS BRANCH IF CLOSEONE IS
|
|
;ACCESSED VIA CLOSEALL.
|
|
(A301) LDA #0 ;Shut the exec flag off.
|
|
(A303) STA EXECFLAG ;NOTE: THIS INSTRUCTION IS NEVER CARRIED
|
|
;OUT IF ACCESSED VIA CLOSEALL. (An active exec file
|
|
;was already detected and skipped by the "BEQ CHKNXBUF"
|
|
(A306) ;instruction at $A323.)
|
|
FREEBUFF LDY #0
|
|
TYA ;Free up the DOS buffer by poking a $00 in the
|
|
STA (A3L),Y ;first byte of the filename field.
|
|
(A30B) JSR BUFS2PRM
|
|
|
|
* Get addresses of the DOS buffers from chain
|
|
* buffer and put then in the 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 name buf from the chain pointer
|
|
INY ;buffer & put them in the FM parameter list.
|
|
CPY #38 ;(P.S. Addr of NEXT filename buffer is
|
|
BNE ADRINPRM ;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 execute the close function.
|
|
|
|
(AB06)
|
|
FILEMGR TSX ;Save stk pointer so we can rtn to caller.
|
|
STX STKSAV ;Save stk pointer.
|
|
(AB0A) JSR RSTRFMWA ;Copy contents of FM work buf (in DOS chain)
|
|
;to FM work area (not in buffer chain).
|
|
|
|
(AE6A)
|
|
RSTRFMWA JSR SELWKBUF ;Find FM work buf.
|
|
|
|
* Get the addr of
|
|
* the FM work buffer
|
|
* from the FM parm
|
|
* list & stick it
|
|
* it in the A4L/H
|
|
* pointer.
|
|
(AF08)
|
|
SELWKBUF LDA #0
|
|
(AF0A) BEQ PT2FMBUF
|
|
|
|
(AF12)
|
|
PT2FMBUF LDA WRKBUFFM,X
|
|
STA A4L
|
|
LDA WRKBUFFM+1,X
|
|
STA A4L+1
|
|
(AF1C) RTS
|
|
|
|
(AE6D) LDY #0 ;Zero out rtn code
|
|
(AE6F) STY RTNCODFM ;in FM parm list
|
|
(AE72) ;to signal no errs.
|
|
STORFMWK LDA (A4L),Y ;Copy FM work buffer
|
|
STA FMWKAREA,Y ;(in chain) to FM
|
|
INY ;wrk area (nonchain).
|
|
CPY #45
|
|
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, got range error.
|
|
ASL ;Double val of opcode & get addr of
|
|
TAX ;appropriate function handler from tbl.
|
|
LDA FMFUNCTB+1,X ;Stick addr 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 afterr doing the CLOSE function.
|
|
* (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. Got a zeroed-out T/S link or a
|
|
;zeroed-out data pair in T/S list.
|
|
;(Not applicable to the close function.)
|
|
(A6B4) JMP OTHRERR ;(See dis'mbly of errors.)
|
|
------------
|
|
|
|
(A6C3)
|
|
FMDRVRTN RTS ;Return to caller of FMDRIVER.
|
|
|
|
(A32D) JMP CLOSEALL ;Go to CLOSERTS via CLOSEALL.
|
|
------------
|
|
|
|
CLOSERTS RTS
|
|
(A330) ============
|
|
|
|
(A25C) PLA ;Get argument issued with maxfiles command
|
|
STA MXFILVAL ;and save it in the main variable table.
|
|
(A260) JMP BILDBUFS ;Go build maxfiles # of buffers.
|
|
------------
|
|
|
|
* Build the DOS buffers
|
|
|
|
* Point A3L/H at FIRST DOS FILENAME BUFFER. Example calcs for FIRST set of DOS
|
|
* (Note: First DOS name buffer is lowest buffers on a 48K machine
|
|
* numbered but highest in memory.) ----------------------------------
|
|
(A7D4)
|
|
BILDBUFS SEC ;Wasted byte, might as well be a "NOP".
|
|
LDA ADOSFNB1 ;Get addr of 1rst filename field
|
|
STA A3L ;and put it in A3L/H.
|
|
LDA ADOSFNB1+1
|
|
(A7DD) STA A3L+1 (A3L/+1) = ($9CD3)
|
|
|
|
* Get # of maxfiles wanted & store it
|
|
* in the temporary counter (TEMPBYT).
|
|
(A7DF) LDA MXFILVAL
|
|
(A7E2) STA TEMPBYT
|
|
|
|
* Free buffer by zeroing out the
|
|
* 1rst byte of the filename field.
|
|
(A7E5)
|
|
ZDOSBUFN LDY #0 (y) = 0
|
|
TYA (a) = 0
|
|
(A7E8) STA (A3L),Y (9CD3),0: 00 --> 9CD3:00
|
|
|
|
* Point link in chain pointers buffers
|
|
* at the FM WORK BUFFER.
|
|
(A7EA) LDY #30 ;Set (y) to index 1rst link (y) = 1E
|
|
;in chain pointers buffer.
|
|
(A7EC) SEC
|
|
LDA A3L ;Subtract 45 from low byte of addr (a) = D3
|
|
SBC #45 ;of filename buf to calc low byte (a) = D3 - 2D = A6
|
|
STA (A3L),Y ;of addr of FM work buf & put it in 9CD3,1E: A6 --> 9CF1: A6
|
|
PHA ;the chain pointer & on the stk. (a) = A6
|
|
LDA A3L+1 ;Subtract carry from hi byte of addr of (a) = 9C
|
|
SBC #0 ;filename buf to get hi byte of FM wrk buf. (a) = 9C - 0 = 9C
|
|
(A7F8) INY ;Kick up (y) to index addr of hi byte of (y) = 1F
|
|
;link in chain pointers.
|
|
(A7F9) STA (A3L),Y ;Store hi byte of addr of FM wrk buf 9CD3,1F: 9C --> 9CF2: 9C
|
|
;in the link.
|
|
;(Note: Above calculations affect (a)
|
|
;but not A3L/H.)
|
|
|
|
* Point link in chain pointers buffer
|
|
* at the T/S LIST SECTOR BUFFER.
|
|
(A7FB) TAX ;Put hi byte of addr of FM wrk buf in (x) = 9C
|
|
(A7FC) DEX ;(x) & kick it down so it indexes hi byte (x) = 9B
|
|
;of T/S list buf. (T/S list buf is $100
|
|
;bytes long.)
|
|
(A7FD) PLA ;Get low byte of addr of FM wrk buf back (a) = A6
|
|
PHA ;from stack.
|
|
INY ;Kick index up to link in chain pointers. (y) = 20
|
|
(A800) STA (A3L),Y ;Put low byte of addr of FM wrk buf in 9CD3,20: A6 ---> 9CF3: A6
|
|
;link buffer's pointer.
|
|
(A802) TXA ;Get hi byte of T/S list buf in (a). (a) = 9B
|
|
INY ;Kick up index in chain pointers buf. (y) = 21
|
|
(A804) STA (A3L),Y ;Set hi byte of link in chain pointers. 9CD3,21: 9B --> 9CF4: 9B
|
|
|
|
* Point the link in the chain pointers
|
|
* buffer at the DATA SECTOR BUFFER.
|
|
(A806) TAX ;Put hi byte of addr of T/S list buf (a) = 9B
|
|
(A807) DEX ;in (x) & kick it down to correspond to (x) = 9A
|
|
;hi byte of addr of data sec buf.
|
|
(A808) PLA ;Get low byte of T/S list buf from (a) = A6
|
|
(A809) PHA ;stack & use it for low byte of data Saved (a) = A6
|
|
;sec buf (cause they are exactly 1 page
|
|
;apart).
|
|
(A80A) INY ;Kick up index to chain pointers buf. (y) = 22
|
|
(A80B) STA (A3L),Y ;Put low byte of addr of data sec buf in 9CD3,22: A6 --> 9CF5: A6
|
|
;the link buf.
|
|
(A80E) INY ;Kick up index to chain pointers buf. (y) = 23
|
|
TXA ;Get hi byte of adr of T/S list buf & (a) = 9A
|
|
(A80F) STA (A3L),Y ;designate it as hi byte of link. 9CD3,23: 9A --> 9CF6: 9A
|
|
|
|
* Reduce counter for number
|
|
* of buffers built so far.
|
|
(A811) DEC TEMPBYT ;If counter goes to zero, then just
|
|
(A814) BEQ ZLNK2NXT ;did last buffer & should zero out link.
|
|
|
|
* Not done all bufs yet so point
|
|
* link in chain pointers at NEXT
|
|
* FILENAME BUFFER.
|
|
(A816) TAX ;Set (x) = low byte of addr of data (a) = 9A
|
|
;sector buffer.
|
|
(A817) PLA ;Get low byte of addr of data sec buf (a) = A6
|
|
;back off of stack.
|
|
(A818) SEC ;Subtract 38 from low byte of data sec
|
|
SBC #38 ;to index NEXT filename field buf. (a) = A6-26 = 80
|
|
INY ;Kick up index to chain pointers buf. (y) = 24
|
|
STA (A3L),Y ;Store low byte of next filename buf 9CD3,24: 80 --> 9CF7: 80
|
|
PHA ;in link & then save it on stk. Saved (a) = 80
|
|
TXA ;Get hi byte of data sec buf from (x) (a) = 9A
|
|
(A820) SBC #0 ;& subtract carry (in case cross (a) = 9A
|
|
;page boundary) to get (a) = hi byte
|
|
;of NEXT filename field buffer.
|
|
(A822) INY ;Kick index up to chain pointers buf (y) = 25
|
|
(A823) STA (A3L),Y ;& store hi byte of NEXT filename field 9CD3,25: 9A --> 9CF8: 9A
|
|
;in link.
|
|
|
|
* Set A3L/H to point to NEXT
|
|
* filename field buffer.
|
|
(A825) STA A3L+1 A3L+1 = 9A
|
|
PLA (a) = 80
|
|
STA A3L A3L = 80 therefore, (A3L/+1) --> ($9A80)
|
|
(A82A) JMP ZDOSBUFN ;Go back to free NEXT DOS filename
|
|
------------ ;buffer & build more DOS bufs.
|
|
|
|
* No more buffers to build so zero out
|
|
* the link that would normally point to
|
|
* the next filename field buffer.
|
|
(A82D)
|
|
ZLNK2NXT PHA ;Save low byte of addr of data buf on stk.
|
|
LDA #0 ;Zero out link to next filename field buf.
|
|
INY
|
|
STA (A3L),Y
|
|
INY
|
|
(A834) STA (A3L),Y
|
|
|
|
* Check which basic is active.
|
|
(A836) LDA ACTBSFLG ;Check if active basic is FP or Integer.
|
|
(A839) 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.
|
|
(A83B) PLA
|
|
STA MEMSIZ+1
|
|
STA FRETOP+1
|
|
PLA
|
|
STA MEMSIZ
|
|
STA FRETOP
|
|
(A845) RTS ;Exit to caller of maxfiles cmd.
|
|
============ ;Normally exits to AFTRCMD ($A17D) in the
|
|
;command parsing and processing routines.
|
|
|
|
* Using Integer, so set HIMEM
|
|
* & program pointer (INTPGMST).
|
|
(A846)
|
|
SETINTPT PLA
|
|
STA HIMEM+1
|
|
STA INTPGMST+1
|
|
PLA
|
|
STA HIMEM
|
|
STA INTPGMST
|
|
(A850) RTS ;Exit to caller of maxfiles cmd.
|
|
============ ;Normally exits to AFTRCMD ($A17D) in the
|
|
;command parsing and processing routines.
|
|
|
|
|
|
|
|
|
|
DOS BUFFER DEFAULT LOCATIONS ON A 48K MACHINE
|
|
|
|
|
|
l Memory available to Applesoft program l
|
|
l l
|
|
Addrs on 48 K system l l Offset from
|
|
(when MXFILVAL = 3) l l start of DOS buffer
|
|
l================================================================l
|
|
>>>>>>>>>>>>>>> $9600 l l $00
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l Data Sector Buffer l
|
|
^ l (DOS Buffer 3) l
|
|
^ l (256 bytes) l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ l l
|
|
^ $96FF l l $0FF
|
|
^ l----------------------------------------------------------------l
|
|
^ >>>>>>>>> $9700 l l $100
|
|
^ ^ l l
|
|
^ ^ l l
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l T/S List Sector Buffer l ^
|
|
^ ^ l (DOS Buffer 3) l Z
|
|
^ ^ l (256 bytes) l E
|
|
^ ^ l l R
|
|
^ ^ l l O
|
|
^ ^ l l S
|
|
^ ^ l l
|
|
^ ^ l l O
|
|
^ ^ l l U
|
|
^ ^ l l T
|
|
^ ^ l l ^
|
|
^ ^ $97FF l l $1FF ^
|
|
^ ^ l----------------------------------------------------------------l ^
|
|
^ ^ >>> $9800 l l $200 ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l FM Work Area Buffer l ^
|
|
^ ^ ^ l (DOS Buffer 3) l ^
|
|
^ ^ ^ l (45 bytes) l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ $982C l l $22C ^
|
|
^ ^ ^ l----------------------------------------------------------------l ^
|
|
^ ^ ^ $982D l l $22D <<<< ^
|
|
^ ^ ^ l l ^ ^
|
|
^ ^ ^ l Filename Field Buffer l ^ ^
|
|
^ ^ ^ l (DOS Buffer 3) l ^ ^
|
|
^ ^ ^ l (30 bytes) l ^ ^
|
|
^ ^ ^ $984A l l $24A ^ ^
|
|
^ ^ ^ l----------------------------------------------------------------l ^ ^
|
|
^ ^ ^...$984B l l $24B ^ ^
|
|
^ ^.................l Chain Pointers Buffer l ^ ^
|
|
^.......................l (DOS Buffer 3) l ^ ^
|
|
$9852 l (8 bytes) ($0000) l $252...........^
|
|
l=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-l ^
|
|
>>>>>>>>>>>>>>> $9853 l l $00 ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l Data Sector Buffer l ^
|
|
^ l (DOS Buffer 2) l ^
|
|
^ l (256 bytes) l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ $9952 l l $0FF ^
|
|
^ l----------------------------------------------------------------l ^
|
|
^ >>>>>>>>> $9953 l l $100 ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l T/S List Sector Buffer l ^
|
|
^ ^ l (DOS Buffer 2) l ^
|
|
^ ^ l (256 bytes) l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ $9A52 l l $1FF ^
|
|
^ ^ l----------------------------------------------------------------l ^
|
|
^ ^ >>> $9A53 l l $200 ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l FM Work Area Buffer l ^
|
|
^ ^ ^ l (DOS Buffer 2) l ^
|
|
^ ^ ^ l (45 bytes) l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ $9A7F l l $22C ^
|
|
^ ^ ^ l----------------------------------------------------------------l ^
|
|
^ ^ ^ $9A80 l l $22D <<<<<<<<<<<
|
|
^ ^ ^ l l ^ ^
|
|
^ ^ ^ l Filename Field Buffer l ^ ^
|
|
^ ^ ^ l (DOS Buffer 2) l ^ ^
|
|
^ ^ ^ l (30 bytes) l ^ ^
|
|
^ ^ ^ $9A9C l l $24A ^ ^
|
|
^ ^ ^ l----------------------------------------------------------------l ^ ^
|
|
^ ^ ^...$9A9D l l $24B ^ ^
|
|
^ ^.................l Chain Pointers Buffer l ^ ^
|
|
^.......................l (DOS Buffer 2) l ^ ^
|
|
$9AA5 l (8 bytes) l $252 ...^ ^
|
|
l=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-l ^
|
|
>>>>>>>>>>>>>>> $9AA6 l l $00 ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l Data Sector Buffer l ^
|
|
^ l (DOS Buffer 1) l ^
|
|
^ l (256 bytes) l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ l l ^
|
|
^ $9BA5 l l $0FF ^
|
|
^ l----------------------------------------------------------------l ^
|
|
^ >>>>>>>>> $9BA6 l l $100 ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l T/S List Sector Buffer l ^
|
|
^ ^ l (DOS Buffer 1) l ^
|
|
^ ^ l (256 bytes) l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ l l ^
|
|
^ ^ $9CA5 l l $1FF ^
|
|
^ ^ l----------------------------------------------------------------l ^
|
|
^ ^ >>> $9CA6 l l $200 ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l FM Work Area Buffer l ^
|
|
^ ^ ^ l (DOS Buffer 1) l ^
|
|
^ ^ ^ l (45 bytes) l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ l l ^
|
|
^ ^ ^ $9CD2 l l $22C ^
|
|
^ ^ ^ l----------------------------------------------------------------l ^
|
|
^ ^ ^ $9CD3 l l $22D <<<< ^
|
|
^ ^ ^ l l ^ ^
|
|
^ ^ ^ l Filename Field Buffer l ^ ^
|
|
^ ^ ^ l (DOS Buffer 1) l ^ ^
|
|
^ ^ ^ l (30 bytes) l ^ ^
|
|
^ ^ ^ $9CF0 l l $24A ^ ^
|
|
^ ^ ^ l----------------------------------------------------------------l ^ ^
|
|
^ ^ ^...$9CF1 l ex. A6, 9C l $24B ^ ^
|
|
^ ^.................l ex. A6, 9B Chain Pointers Buffer l ^ ^
|
|
^.......................l ex. A6, 9A (DOS Buffer 1) l ^ ^
|
|
$9CF8 l (8 bytes) ex. 80, 9A l $252...........^
|
|
l=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-l ^
|
|
$9CF9 l (7 unused bytes) l $253 ^
|
|
$9CFF l l $259 ^
|
|
l================================================================l ^
|
|
$9D00 l (ADOSFNB1/+1)---> l..........^
|
|
l DOS l
|
|
l l
|
|
(Normally, the byte at $3D2 corresponds to the page
|
|
number of the start of DOS. This byte can there4 be used
|
|
to determine if DOS is at its "normal" location.
|
|
If $3D2 contains a value less than #$9D then the computer
|
|
has less than 48K of RAM. A value equal to #$9D means that
|
|
DOS is at its normal 48K location whereas a larger value
|
|
describes a machine with at least 48K of memory. In the
|
|
later instance, DOS may reside on the language card.)
|
|
|
|
Note that the first two bytes of DOS point to the first
|
|
DOS buffer at its filename field. Therefore, once you
|
|
find the start of DOS (via the high byte of the warm-
|
|
start vector), you can use the first two bytes of DOS to
|
|
locate the DOS buffer chain even if an editor program is
|
|
installed between DOS and its buffers.
|
|
|