     opt 7›››*------------------------------*›*The "M:" driver               *›*Using memory as a device      *›*Includes installation program *›*                              *›*Written by Bill Wilkinson     *›*for January, 1982, COMPUTE!   *›*------------------------------*›››*- Converted from MAC to QA by Mikey›››ICAUX1 equ $34A ; The AUX1 byte of IOCB›OPOUT  equ 8    ; Mode 8 is OPEN for OU›                ; TPUT›MEMLO  equ $2E7 ; pointer to bottom of›                ; free RAM›MEMTOP equ $2E5 ; pointer to top of free›                ; RAM›FR1    equ $E0  ; Fltg Pt Register 1,›                ; scratch››STATUSOK  equ 1  ; I/O was good›STATEOF equ $88  ; reached an end-of-file››HATABS equ $31A›HIGH   equ $100 ; divisor for high byte›LOW    equ $FF  ; mask for low byte››*-Installation of the driver››   org $3000  *-Change it if you wish››*- This first routine is simply›*- used to connect the driver›*- to Atari's handler address›*- table.››LOADANDGO equ *››  LDX #0         ; We begin at start of table››SEARCHING equ *››  LDA HATABS,X   ; Check device name›  BEQ EMPTYFOUND ; Found last one›  CMP #'M'       ; Already have M: ?›  BEQ MINSTALLED ; Yes, don't reinstall›  INX›  INX›  INX            ; Point to next entry›  BNE SEARCHING  ; and keep looking›  RTS            ; Huh? Impossible!!!››*- We found the current end of the›*- table...so extend it.››EMPTYFOUND equ *››  LDA #'M'       ; Our device name, "M:"›  STA HATABS,X   ; is first byte of entry›  LDA <MDRIVER   ; LOW›  STA HATABS+1,X ; LSB of driver addr›  LDA >MDRIVER   ; HIGH›  STA HATABS+2,X ; and MSB of addr›  LDA #0›  STA HATABS+3,X ; A new end for the table››*-  now change LOMEM so BASIC won't›*-  overwrite us.››MINSTALLED equ *››  LDA <DRIVERTOP    ;LOW›  STA MEMLO         ; LSB of top addr›  LDA >DRIVERTOP    ;HIGH›  STA MEMLO+1       ; and MSB therof››*- and that's all we have to do!››  RTS››*- This entry point is provided›*- so that BASIC can reconnect›*- the driver via a USR(RECONNECT)››RECONNECT equ *››  PLA›  BEQ LOADANDGO ; No parameters, I hope›  TAY››PULLTHEM equ *››  PLA›  PLA           ; get rid of a parameter›  DEY›  BNE PULLTHEM  ; and pull another›  BEQ LOADANDGO ; go reconnect››*- The driver itself›*- Recall that all drivers must›*- be connected to OS through›*- a driver routines address table.››MDRIVER equ *››  dta a(MOPEN-1)   ; The addresses must›  dta a(MCLOSE-1)  ; be given in this›  dta a(MGETB-1)   ; order and must›  dta a(MPUTB-1)   ; be one (1) less›  dta a(MSTATUS-1) ; than the actual›  dta a(MXIO-1)    ; address›  JMP MINIT        ; This is for safety only››*- For many drivers, some of these›*- routines are not needed, and›*- can effectively be null routines›*- A null routine should return›*- a one (1) in the Y-register›*- to indicate success.››MXIO  equ *›MINIT equ *››  LDY #1 ; success›  RTS››*-If a routine is omitted because›*-it is illegal (reading from a›*-printer, etc.), simply pointing›*-to an RTS is adequate, since›*-Atari OS preloads Y with a›*-'Function Not Implemented' error›*-return code.››*-The driver function routines›*-Now we begin the code for the›*-routines that do the actual›*-work››MOPEN equ *››  LDA ICAUX1,X    ; Check type of open›  AND #OPOUT      ; Open for output?›  BEQ OPENFORREAD ; No...assume for input›  LDA MEMTOP›  STA MSTART      ; We start storing›  LDY MEMTOP+1    ; ...the bytes›  DEY             ; ...one page below›  STY MSTART+1    ; the supposed top of mem››*- now we join up with mode 4 open››OPENFORREAD equ *››  LDA MSTART     ; simply move the›  STA MCURRENT   ; start pointer›  LDA MSTART+1   ; to the current›  STA MCURRENT+1 ; pointer, both bytes›  LDY #STATUSOK›  RTS ; we don't acknowledge failure››MCLOSE equ *››  LDA ICAUX1,X   ; check mode of open›  AND #OPOUT     ; was for output?›  BEQ MCLREAD    ; no...close input 'file'›  LDA MCURRENT   ; we establish our›  STA MSTOP      ; ...limit so that›  LDA MCURRENT+1 ; ...next use can't›  STA MSTOP+1    ; ...go too far››MCLREAD equ *››  LDY #STATUSOK›  RTS ; and guaranteed to be ok›››››*- This routine puts one byte›*- to the memory for later›*- retrieval.››MPUTB equ *››  PHA             ; save the byte to be PUT›  JSR MOVECURRENT ; get ptr to zero page›  PLA             ; the byte again›  LDY #0›  STA (FR1),Y     ; put the byte, indirectly›  JSR DECCURRENT  ; point to nxt byte›  RTS             ; that's all››*- routine to get a byte put›*- in memory before.››MGETB equ *››  JSR MSTATUS    ; any more bytes?›  BCS MGETRTS    ; no...error›  LDY #0›  LDA (FR1),Y    ; yes...get a byte›  JSR DECCURRENT ; and point to next byte››MGETRTS equ *››  RTS››*- check the status of the driver›*- this routine is only valid›*- when READing the 'file'...›*- "M:" never gets errors when›*- writing.››MSTATUS equ *››  JSR MOVECURRENT ; current ptr to zero page›  CMP MSTOP       ; any more bytes to get?›  BNE MSTOK       ; yes›  CPY MSTOP+1     ; double chk›  BNE MSTOK       ; yes, again›  LDY #STATEOF    ; oops...›  SEC             ; no more bytes›  RTS››MSTOK equ *››  LDY #STATUSOK   ; all is okay›  CLC             ; flag for MGETB›  RTS››*-Miscellaneous subroutines››*- finally, we have a couple of›*- short and simple routines to›*- manipulate MCURRENT, the ptr›*- to the currently accessed byte›››*- MOVECURRENT simply moves›*- MCURRENT to the floating›*- point register, FR1, in›*- zero page.  FR1 is always›*- safe to use except in the›*- middle of an expression.››MOVECURRENT equ *››  LDA MCURRENT›  STA FR1        ; notice that we use›  LDY MCURRENT+1 ; both the A and›  STY FR1+1      ; Y registers...this›  RTS            ; is for MSTATUS use››*- DECCURRENT simply does a two›*- byte decrement of the MCURRENT›*- pointer and returns with the›*- Y register indicating OK status.›*- NOTE that the A register is›*- left undisturbed.››DECCURRENT equ *››  LDY MCURRENT   ; check LSB's value›  BNE DECLOW     ; if non-zero, MSB is ok›  DEC MCURRENT+1 ; if zero, need to bump MSB››DECLOW equ *››  DEC MCURRENT  ; now bump the LSB›  LDY #STATUSOK ; as promised›  RTS››*-RAM usage and clean up››*- END OF CODE››*- Now we define our storage›*- locations.›*- MCURRENT holds the pointer to›*- the next byte to be PUT or GET››MCURRENT dta a(0)››*- MSTOP is set by CLOSE to point›*- to the last byte PUT, so GET›*- won't try to go past the end›*- of data.››MSTOP dta a(0)››*- MSTART is derived from MEMTOP›*- and points to the first byte›*- stored.  The bytes are stored›*- in descending addresses until›*- MSTOP is set by CLOSE.››MSTART dta a(0)››*- DRIVERTOP becomes the new›*- contents of MEMLO››DRIVERTOP org *+$FF    &$FF00›››     org $2E0›     dta a(loadandgo)››     end››