💾 Archived View for mirrors.apple2.org.za › archive › www.textfiles.com › apple › ANATOMY › fnposn.t… captured on 2024-08-19 at 03:02:16.
View Raw
More Information
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
- ================================================================*
- *
- 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).)