1251 lines
29 KiB
NASM
1251 lines
29 KiB
NASM
;
|
|
; Originally coded in 2009 by Matthew A. Hudson hexsane
|
|
; at gmail.com
|
|
; Code style & format borrowed from CFFA v1 source code
|
|
; use ca65 to assemble (options elude me as I wrote this code
|
|
; over a decade ago as I type this)
|
|
;
|
|
; HP-IB AMIGO protocol ROM replacement for genuine Apple II GP-IB controller.
|
|
;
|
|
; Was assembled and working for floppy drive in HP9133xv
|
|
; It will work with the hard drive but you will need to change the
|
|
; geometry and re assemble.
|
|
;
|
|
; Note about assembly: I had to offset the code by either 128 or 256 bytes
|
|
; (meaning you lose that space in the ROM) but I can't recall why. You may
|
|
; need to fiddle around with options to get it in the correct location to
|
|
; make the card happy. I've forgotten most of the Apple II I/O layout at this
|
|
; point in time.
|
|
;
|
|
; There is probably code in here from other sources but I couldn't recall from
|
|
; who at this point. If you see something that needs credit please let me know
|
|
; and I will happily do so.
|
|
;
|
|
; Constant equates and 'magic' numbers
|
|
;
|
|
CR = $0D ; ASCII carriage return
|
|
RDY = $AE ; offset in ROM to "READY." message
|
|
VBLNK = $20 ; mask for vertical blank bit in VIA
|
|
OFFM = $00 ; turns off AUTO, TRACE or STEP
|
|
POSMSK = $7F ; mask to force positive byte
|
|
AUTOM = $01 ; AUTO mode marker
|
|
TRACEM = $02 ; TRACE mode marker
|
|
STEPM = $03 ; STEP mode marker
|
|
SCREEN = $8000 ; SCREEN RAM starting location
|
|
TKNTO = $A4 ; BASIC token for TO statement
|
|
TKNMIN = $AB ; BASIC token for minus sign: -
|
|
MAXLIN = $F9FF ; maximum line number for BASIC (63999)
|
|
BASPG = $B4 ; BASIC page for direct mode CHRGET call
|
|
; ; -- Handle new BASIC line input page.
|
|
VERSION = 0
|
|
; Zero page locations
|
|
;
|
|
COUNT = $0005 ; temporary byte storage for counters, etc.
|
|
_FLAG1 = $0009 ; Misc. flag or index value
|
|
TMPINT = $0011 ; integer temp
|
|
_STRPTR = $001F ; pointer to string variable
|
|
_TMPTR0 = $0021 ; temporary pointer to BASIC text
|
|
_BASPTR = $0028 ; pointer to start of BASIC program
|
|
_VARPTR = $002A ; pointer to start of BASIC variables
|
|
_ARRPTR = $002C ; pointer to start of BASIC arrays
|
|
_MEMSZ = $0034 ; highest memory location used by BASIC
|
|
CURRLN = $0036 ; current BASIC line number
|
|
_VARNAM = $0042 ; current VARIABLE name
|
|
_VARADR = $0044 ; address of VARIABLE
|
|
TMPTR1 = $0055 ; temporary storage for integers or pointers
|
|
TMPTR2 = $0057 ; " "
|
|
TMPTR3 = $005C ; " "
|
|
CYLH = $0055
|
|
CYLL = $0056
|
|
HEAD = $0057
|
|
SECTOR = $0058
|
|
_FACCM = $005F ; f.p. mantissa (int. storage for conversion)
|
|
CHRGET = $0070 ; The infamous BASIC character/token fetch
|
|
CHRGOT = $0076 ; get last character
|
|
TXTPTR = $0077 ; pointer into BASIC program
|
|
MODE = $007C ; OFF, AUTO, STEP or TRACE marker (0,1,2 or 3)
|
|
_LINNUM1 = $0080 ; work area and storage for BASIC line
|
|
_LINNUM2 = $0082 ; numbers used by AUTO and RENUMBER
|
|
_TMPTR4 = $0084 ; temporary pointer
|
|
_TMPTR5 = $0086 ; temporary pointer or byte storage (see below)
|
|
_TMPERR = $0086 ; temporary offset to char used by HELP routine
|
|
A0BYTE = $A0
|
|
A5BYTE = $A5
|
|
|
|
ACBYTE = $80
|
|
BTBYTE = $81
|
|
EFBYTE = $82
|
|
MXHEAD = $83
|
|
MXSECTOR = $84
|
|
MXCYLH = $85
|
|
MXCYLL = $86
|
|
;SPARE1 = $82
|
|
;BYBYTE = $82
|
|
SAVEX = $0087 ; temporary storage for BASIC 'x' register
|
|
_STATUS = $0096 ; BASIC status byte
|
|
_SHIFTKEY = $0098 ; SHIFT key pressed = 1, not pressed = 0
|
|
_LDVERF = $009D ; LOAD/VERIFY flag for cassette
|
|
_NUMCHR = $009E ; number of characters in keyboard buffer
|
|
_REVFLG = $009F ; screen reverse field flag
|
|
TAPETMP1 = $00C7 ; temporary pointers for tape handler
|
|
_TAPETMP2 = $00C9 ; " " "
|
|
_FNLEN = $00D1 ; number of characters in file name
|
|
DEVID = $00D4 ; device ID
|
|
DISKNUM = $033b ; D# from command line.
|
|
_TAPBUFF = $00D6 ; pointer to start of tape buffer
|
|
;
|
|
; stack page
|
|
;
|
|
STKPAG = $0100
|
|
;
|
|
; BASIC input buffer
|
|
;
|
|
INBUFF = $0200 ; direct mode input buffer and work area
|
|
KEYBUFF = $026F ; BASIC keyboard buffer
|
|
;
|
|
; cassette buffer
|
|
;
|
|
SAFTMP1 = $03E0 ; safe temporary when cassette #2 not used
|
|
SAFTMP2 = $03E1 ; " " "
|
|
STEPSZ = $03E2 ; line spacing for AUTO and RENUMBER
|
|
LNBUFF = $03E4 ; Line buffer for TRACE and STEP scrolling
|
|
TRCBUF = $03E6 ; buffer for displayed TRACE lines (integers)
|
|
;
|
|
; BASIC entry points
|
|
;
|
|
KWDLST = $C092 ; list of BASIC keywords
|
|
PRTERR = $C355 ; print error message
|
|
ERRMSG = $C377 ; print ERROR
|
|
RDYMSG = $B3FF ; print READY.
|
|
FIXLINKS = $C439 ; reset BASIC line links
|
|
LOOKUP = $b4fb ; get BASIC token for keyword
|
|
FINDLINE = $C52C ; get ptr to BASIC line. num ($11), ptr: ($5C)
|
|
RST_PTRS = $C572 ; reset BASIC pointers to default values
|
|
RD_INT = $C873 ; convert ASCII string to integer in $11,$12
|
|
PUT_CRLF = $C9DE ; print CR/LF to device
|
|
PUT_STRING = $bb1d ; prepare and print ASCII string to device
|
|
PRTSTR = $CA22 ; print string
|
|
PUTCHR = $bb46 ; print character
|
|
SYNERR = $CE03 ; display ?SYNTAX ERROR msg
|
|
LOCVAR = $D069 ; find an f.p. variable by name
|
|
FX2FLT = $D26D ; convert fixed point to floating point
|
|
LDFACC = $DAAE ; load f.p. number fo FACC1
|
|
INT2FP = $DB55 ; convert integer to f.p.
|
|
PRTLIN = $DCD5 ; print line number
|
|
PRTINT = $cf83 ; print integer in a(hi),x(lo)
|
|
CNV_PRT = $DCE3 ; convert f.p. in FACC1 to ASCII and print
|
|
FP2ASC = $DCE9 ; convert to ASCII string at bottom of stack
|
|
;PARSEDOS = $de2c ; Parse DOS BASIC command line
|
|
PARSEDOS = $dc68 ; Parse DOS BASIC command line
|
|
PRTHEX = $d722 ; Print A as HEX to output
|
|
;
|
|
; Screen editor
|
|
;
|
|
NUMCHK = $d3aa ; clear carry if 'a' contains ASCII digit
|
|
;
|
|
; I/O ports
|
|
VIA = $E840 ; misc. operating system flags and VBLANK
|
|
;
|
|
; Kernel (kernal) entry points
|
|
;
|
|
PRTMON = $F156 ; print MONITOR message at index in 'y'
|
|
PRTLOAD = $F3E6 ; print LOAD message
|
|
PRTRDY = $F3EF ; print READY. message
|
|
PRTSRCH = $F40A ; print SEARCHING message
|
|
GETPARM = $F47d ; get device parameters
|
|
GETHDR = $F494 ; get tape program header
|
|
PRTFNF = $F56E ; print FILE NOT FOUND message
|
|
SRCH_HDR = $F5A6 ; search tape for next header
|
|
RD_HDR = $F63C ; get tape program start & end addresses
|
|
SET_BUFF = $F656 ; set buffer start address
|
|
WT_PLAY = $F812 ; wait for cassette PLAY switch
|
|
RD_TAPE = $F85E ; read cassette tape
|
|
WT_IO = $F8E6 ; wait for I/O completion
|
|
STOPKEY = $FFE1 ; check for stop key and restart BASIC
|
|
|
|
; IEEE 488
|
|
|
|
NRFDOUT = $e840
|
|
NDACOUT = $e821
|
|
EOIOUT = $e811
|
|
DAVOUT = $e823
|
|
HIGH = $3c
|
|
LOW = $34
|
|
DATAOUT = $e822
|
|
DATAIN = $e820
|
|
NRFDIN = $e840
|
|
DAVIN = $e840
|
|
ATNOUT = $e840
|
|
NDACIN = $e840
|
|
EOIIN = $e810
|
|
|
|
;
|
|
; AMIGO DOS START
|
|
;
|
|
; Call with SYS(28672)
|
|
;
|
|
;.segment "szzz"
|
|
;.org $7000
|
|
.word *+2
|
|
;.segment "STARTUP"
|
|
;.code
|
|
|
|
AMIGODOS: jmp INITROM ; Toolkit initialization.
|
|
; Need jump table here.
|
|
INITROM: ldx #$07 ; Initialize Toolkit ROM.
|
|
@B: lda WEDGE-1,x ; Gopy 'wedge' to CHRGET
|
|
sta TXTPTR+1,x ; following TXTPTR.
|
|
dex
|
|
bne @B
|
|
lda #<CPYRT ; Display PAICs copyright
|
|
ldy #>CPYRT ; notice.
|
|
jsr PUT_STRING
|
|
lda #$05
|
|
sta DEVID ; Set default DEVICE BYTE FIXME
|
|
lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
rts
|
|
;jmp INITVAR ; Initialize Toolkit vars.
|
|
;
|
|
; 'wedge' code for insertion in CHRGET routine
|
|
;
|
|
WEDGE: jmp AD_ENTRY
|
|
brk ; Location for MODE byte.
|
|
jmp AD_CONT
|
|
;
|
|
; This is the entry point for the Toolkit 'wedge' code. Normal BASIC
|
|
; calls to the CHRGET routine are intercepted to test for Toolkit
|
|
; command processing. If no Toolkit action is performed, BASIC is
|
|
; continued.
|
|
;
|
|
AD_ENTRY: pha ; Toolkit entry from CHRGET wedge.
|
|
stx SAVEX ; Save 'x' register for BASIC.
|
|
lda TXTPTR+1 ; Test for direct mode:
|
|
cmp #>INBUFF ; - are we pointing into
|
|
bne @F ; the BASIC buffer? ($02XX)
|
|
lda TXTPTR
|
|
cmp #<INBUFF ; - start of buffer? ($0200)
|
|
beq SCNBUF ; Branch if in Direct mode.
|
|
bne MODCHK ; Branch always.
|
|
@F: lda TXTPTR
|
|
; sta TMPERR ; We're in program space
|
|
MODCHK: lda MODE ; Check mode.
|
|
; beq RTNBAS ; Just continue if mode = OFF(0/BRK).
|
|
; bne @F
|
|
;@F: jmp RTNBAS ; NOT USING MODES
|
|
RTNBAS: ldx SAVEX ; Restore 'x' register.
|
|
pla ; Get saved character
|
|
cmp #'9'+1 ; and set up for a
|
|
bcs AD_EX ; return to BASIC.
|
|
AD_CONT: cmp #' ' ; Continue with BASIC.
|
|
bne @F ; Skip spaces.
|
|
jmp CHRGET
|
|
@F: jmp NUMCHK ; Clear carry if number.
|
|
AD_EX: rts
|
|
|
|
SCNBUF:
|
|
tsx ; Start scan of BASIC buffer.
|
|
lda STKPAG+3,x ; Check previous caller loc.
|
|
cmp #BASPG ; BASIC direct mode?
|
|
bne MODCHK ; IF not, check mode byte.
|
|
ldy #$00 ; ELSE scan buffer.
|
|
sty COUNT
|
|
;
|
|
; Scan the BASIC input buffer (in direct mode) and test the character
|
|
; string for a match with one of the DOS commands. The count of the
|
|
; found command is used to index into a jump table, (ADADDRHI & ADADDRLO)
|
|
;
|
|
FNDCMD: ldx #$FF
|
|
@B: inx ; Scan buffer.
|
|
lda INBUFF,x
|
|
bmi MODCHK
|
|
cmp #' '
|
|
beq @B ; Skip spaces.
|
|
CMDLP: lda CMDLIST,y ; Get next character from
|
|
beq MODCHK ; list of Toolkit cmds.
|
|
eor INBUFF,x
|
|
bne @skf
|
|
iny ; Bump indices on every
|
|
inx ; matched character.
|
|
bpl CMDLP
|
|
@skf:
|
|
cmp #$80 ; Accept keyword if mismatch
|
|
beq GOTTKN ; is caused by terminator.
|
|
@skb: iny ; Otherwise skip characters
|
|
lda CMDLIST-1,y ; to next keyword.
|
|
bpl @skb
|
|
inc COUNT ; Update keyword counter.
|
|
bne FNDCMD ; Branch always (try next cmd).
|
|
GOTTKN: inc TXTPTR ; Bump TXTPTR past this
|
|
dex ; keyword. No need to bump
|
|
bne GOTTKN ; HIGH byte (always $02).
|
|
ldx COUNT
|
|
cpx #$02
|
|
bmi @F
|
|
pla
|
|
pla
|
|
@F: pla
|
|
lda ADADDRHI,x ; Execute Toolkit command.
|
|
pha
|
|
lda ADADDRLO,x
|
|
pha
|
|
rts
|
|
|
|
TEST: .byte "HERE I AM", $0D, $00
|
|
|
|
;
|
|
; This is the DOS keyword (command) list. The last character in each
|
|
; string has the high bit set to facilitate keyword counting.
|
|
;
|
|
CMDLIST:.byte "loo",'p'|128
|
|
.byte "ds",'j'|128
|
|
.byte "statu",'s'|128
|
|
.byte "see",'k'|128
|
|
.byte "heade",'r'|128
|
|
.byte $00
|
|
;
|
|
; DOS command dispatch table. The DOS commands are
|
|
; preceded with an underscore to facilitate browsing the
|
|
; program source code.
|
|
;
|
|
; high bytes of Toolkit routine entry points
|
|
;
|
|
ADADDRHI:.byte >(_LOOP-1)
|
|
.byte >(_DSJ-1)
|
|
.byte >(_STAT-1)
|
|
.byte >(_SEEK-1)
|
|
.byte >(_HEADER-1)
|
|
;
|
|
; low bytes of Toolkit routine entry points
|
|
;
|
|
ADADDRLO:.byte <(_LOOP-1)
|
|
.byte <(_DSJ-1)
|
|
.byte <(_STAT-1)
|
|
.byte <(_SEEK-1)
|
|
.byte <(_HEADER-1)
|
|
|
|
GO_BAS:
|
|
lda #$FF
|
|
sta CURRLN+1
|
|
jmp RDYMSG
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; LISTEN Command 30 TALK Command 30
|
|
;; LOOPBACK Test
|
|
;;
|
|
_LOOP: lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
lda #$05
|
|
sta DEVID
|
|
jsr LISTEN
|
|
lda #$1e ; Write Loopback Record
|
|
sta ACBYTE
|
|
jsr SECLIST
|
|
lda #65
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
lda #66
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
lda #67
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
lda #68
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
lda #69
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
jsr PPUNL
|
|
|
|
jsr TALK
|
|
|
|
lda #$1e ;Read Loopback record
|
|
sta ACBYTE
|
|
|
|
jsr SECTALK
|
|
@B: jsr QIN
|
|
lda ACBYTE
|
|
jsr PUTCHR
|
|
lda EFBYTE
|
|
beq @B
|
|
jsr UNTALK
|
|
jmp GO_BAS
|
|
|
|
.IF 0
|
|
PRTHEXI:
|
|
pha
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
clc
|
|
adc #48
|
|
cmp #58
|
|
bmi @F1
|
|
clc
|
|
adc #7
|
|
@F1:
|
|
jsr PUTCHR
|
|
pla
|
|
and #$0f
|
|
clc
|
|
adc #48
|
|
cmp #58
|
|
bmi @F2
|
|
clc
|
|
adc #7
|
|
@F2:
|
|
jsr PUTCHR
|
|
rts
|
|
.ENDIF
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; DOS Command HEADER - Format Disk
|
|
;;
|
|
_HEADER:lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
jsr CHRGET
|
|
jsr LOOKUP
|
|
jsr CHRGET
|
|
jsr PARSEDOS
|
|
|
|
;jsr FORMAT ; FIXME ENABLE
|
|
|
|
; FIXME Will need identify table for these values.
|
|
lda #2
|
|
sta MXHEAD
|
|
lda #16
|
|
sta MXSECTOR
|
|
lda #35
|
|
sta MXCYLL
|
|
lda #0
|
|
sta MXCYLH
|
|
|
|
;Track 0 Sector 0
|
|
lda #$00
|
|
sta HEAD
|
|
sta CYLH
|
|
sta CYLL
|
|
sta SECTOR
|
|
jsr SEEK
|
|
|
|
jsr OWRITE
|
|
|
|
; Output data to be written to sector (256 Bytes Max)
|
|
lda #VERSION ; Our version #
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #00 ; # or tracks (cylinders) hi
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #35 ; # of tracks (cylinders) lo
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #16 ; # of sectors per track
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #2 ; # of heads
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #1 ; #of Partitions
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #00 ; Partition start track
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #01
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #00 ; Partition end track
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #34
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
jsr CWRITE
|
|
|
|
;Track 18 Sector 0
|
|
lda #$00
|
|
sta HEAD
|
|
sta CYLH
|
|
sta SECTOR
|
|
lda #18
|
|
sta CYLL
|
|
jsr SEEK
|
|
|
|
jsr OWRITE
|
|
lda #<(T18SC0)
|
|
sta TAPETMP1
|
|
lda #>(T18SC0)
|
|
sta TAPETMP1+1
|
|
jsr BUILDSECTOR
|
|
jsr CWRITE
|
|
|
|
;Track 18 Sector 1
|
|
jsr NXTSECTOR
|
|
jsr SEEK
|
|
|
|
jsr OWRITE
|
|
lda #<(T18SC1)
|
|
sta TAPETMP1
|
|
lda #>(T18SC1)
|
|
sta TAPETMP1+1
|
|
jsr BUILDSECTOR
|
|
jsr CWRITE
|
|
|
|
;Track 18 Sector 2
|
|
jsr NXTSECTOR
|
|
jsr SEEK
|
|
|
|
jsr OWRITE
|
|
lda #<(T18SC2)
|
|
sta TAPETMP1
|
|
lda #>(T18SC2)
|
|
sta TAPETMP1+1
|
|
jsr BUILDSECTOR
|
|
jsr CWRITE
|
|
|
|
;Track 18 Sector 3
|
|
ldx #3
|
|
@NXTDIRSEC:
|
|
jsr NXTSECTOR
|
|
jsr SEEK
|
|
jsr OWRITE
|
|
lda #18
|
|
inx
|
|
cpx #32
|
|
bne @NOTLAST
|
|
lda #0
|
|
ldx #$ff
|
|
@NOTLAST:
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
txa
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
jsr CWRITE
|
|
cpx #$ff
|
|
bne @NXTDIRSEC
|
|
|
|
jsr CWRITE
|
|
jmp GO_BAS
|
|
|
|
BUILDSECTOR:
|
|
ldy #$00
|
|
sty COUNT
|
|
@NXTBYTE:
|
|
inc COUNT
|
|
lda (TAPETMP1), y
|
|
iny
|
|
cmp #$80
|
|
bmi @SEND
|
|
cmp #$ff ;$ff = End
|
|
beq @DONE
|
|
cmp 'n'|128 ;n+high bit = name
|
|
bne @f1
|
|
ldx #$00 ;FIXME NEED TO VALIDATE FILE NAME/DISK NAME
|
|
@NXTFNCHAR:
|
|
lda $0342,x
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
inx
|
|
cpy $d1
|
|
bne @NXTFNCHAR
|
|
lda #$10
|
|
sec
|
|
sbc $d1
|
|
beq @NXTBYTE
|
|
tax
|
|
@NXTSSPC:
|
|
lda #$a0
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
dex
|
|
bne @NXTSSPC
|
|
jmp @NXTBYTE
|
|
@f1:
|
|
cmp 'i'|128 ;i+high bit = Disk ID
|
|
bne @f2
|
|
lda $033f
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
lda $0340
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
@f2:
|
|
cmp 'r'|128 ;repeat group
|
|
bne @f3
|
|
lda (TAPETMP1), y
|
|
pha ; push counter
|
|
iny ; offset to restore
|
|
@NXTGROUP:
|
|
tya
|
|
pha ; push restore offset
|
|
jsr @NXTBYTE
|
|
pla
|
|
tsx
|
|
dec $100,x
|
|
beq @GROUPDONE
|
|
tay ;restore offset
|
|
jmp @NXTGROUP
|
|
@GROUPDONE: ;Y should be set beyond the group
|
|
pla
|
|
jmp @NXTBYTE
|
|
@f3:
|
|
and #$80
|
|
sta COUNT
|
|
lda (TAPETMP1), y ;Repeat COUNT times
|
|
iny
|
|
@SEND: sta ACBYTE
|
|
jsr QOUT
|
|
dec COUNT
|
|
bne @SEND
|
|
jmp @NXTBYTE
|
|
@DONE:
|
|
rts
|
|
|
|
NXTSECTOR:
|
|
ldx #0
|
|
inc HEAD
|
|
lda HEAD
|
|
cmp MXHEAD
|
|
beq @INCSECTOR
|
|
rts
|
|
@INCSECTOR:
|
|
stx HEAD
|
|
inc SECTOR
|
|
lda SECTOR
|
|
cmp MXSECTOR
|
|
beq @INCCYLL
|
|
rts
|
|
@INCCYLL:
|
|
stx SECTOR
|
|
clc
|
|
lda CYLL
|
|
adc #1
|
|
bcs @INCCYLH
|
|
sta CYLL
|
|
cmp MXCYLL
|
|
beq @ERROR
|
|
rts
|
|
@INCCYLH:
|
|
stx CYLL
|
|
lda CYLH
|
|
adc #1
|
|
bcs @ERROR
|
|
sta CYLH
|
|
cmp MXCYLH
|
|
beq @ERROR
|
|
rts
|
|
@ERROR:
|
|
;FIXME NEED ERROR HERE
|
|
lda #'e'
|
|
jsr PUTCHR
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
brk
|
|
|
|
; Track 18, Sector 0
|
|
T18SC0: .byte 18, 3, 0, 0, 'n'|128, 'i'|128, $81, $a0, 0, 0, $82, $a0, $ff
|
|
; Track 18 Sector 1
|
|
T18SC1: .byte 18, 2, 0, 0, 'i'|128, 0, 0, 8|128, 0
|
|
.byte 31, 1|128, $fe, 4|128, $ff
|
|
.byte 'r'|128, 16, 32, 5|128, $ff, $ff
|
|
.byte 6|128, 0
|
|
.byte 'r'|128, 17, 32, 5|128, $ff, $ff
|
|
.byte 'r'|128, 5, 6|128, 0, $ff
|
|
.byte $ff
|
|
|
|
; Track 18 Sector 2
|
|
T18SC2: .byte 0, $ff, 0, 0, 'i'|128, 0, 0, 8|128, 0
|
|
.byte 'r'|128, 35, 32, 5|128, $ff, $ff
|
|
.byte 'r'|128, 5, 0, 5|128, 0, $ff
|
|
.byte $ff
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; LISTEN Command 12 TALK OpCode 24
|
|
;; FORMAT Low level format the drive for sector writing.
|
|
;; (Internal Subroutine)
|
|
;;
|
|
FORMAT: lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
lda #$05
|
|
sta DEVID
|
|
|
|
jsr LISTEN
|
|
lda #12 ;FORMAT Command
|
|
sta ACBYTE
|
|
jsr SECLIST
|
|
@B:
|
|
lda #24
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda DISKNUM
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #$80
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #9
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda #0
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
jsr PPUNL
|
|
rts
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; LISTEN Command 8 TALK Command 8
|
|
;; Request Status / Send Status
|
|
;;
|
|
_STAT: lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
jsr CHRGET
|
|
jsr LOOKUP
|
|
jsr CHRGET
|
|
jsr PARSEDOS
|
|
|
|
lda DEVID
|
|
bne EXSTAT
|
|
lda #$05
|
|
sta DEVID
|
|
EXSTAT: jsr STAT
|
|
|
|
lda #<ST1
|
|
ldy #>ST1
|
|
jsr PUT_STRING
|
|
lda TMPTR1
|
|
jsr PRTHEX
|
|
lda TMPTR1+1
|
|
jsr PRTHEX
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
|
|
lda #<ST2
|
|
ldy #>ST2
|
|
jsr PUT_STRING
|
|
lda TMPTR1+2
|
|
jsr PRTHEX
|
|
lda TMPTR1+3
|
|
jsr PRTHEX
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
jmp GO_BAS
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Request Status / Send Status (Internal Subroutine)
|
|
;;
|
|
STAT:
|
|
jsr LISTEN
|
|
lda #8 ; Request Status
|
|
sta ACBYTE
|
|
jsr SECLIST
|
|
lda #3
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
lda DISKNUM ; Disk (Unit) Number
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
jsr PPUNL
|
|
|
|
jsr TALK
|
|
lda #8 ;Send Status
|
|
sta ACBYTE
|
|
jsr SECTALK
|
|
|
|
jsr QIN
|
|
lda ACBYTE
|
|
sta TMPTR1
|
|
jsr QIN
|
|
lda ACBYTE
|
|
sta TMPTR1+1
|
|
|
|
jsr QIN
|
|
lda ACBYTE
|
|
sta TMPTR1+2
|
|
jsr QIN
|
|
lda ACBYTE
|
|
sta TMPTR1+3
|
|
|
|
@B: jsr QIN
|
|
lda ACBYTE
|
|
lda EFBYTE
|
|
beq @B
|
|
jsr UNTALK
|
|
rts
|
|
|
|
ST1: .asciiz "st1:$"
|
|
ST2: .asciiz "st2:$"
|
|
STDSJ: .asciiz "dsj:"
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; TALK Command 16
|
|
;; _DSJ - Device Specified Jump
|
|
;;
|
|
_DSJ: lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
jsr CHRGET
|
|
jsr LOOKUP
|
|
jsr CHRGET
|
|
jsr PARSEDOS
|
|
|
|
lda DEVID
|
|
bne @HAVEDV
|
|
lda #$05
|
|
sta DEVID
|
|
@HAVEDV:jsr DSJ
|
|
lda #<STDSJ
|
|
ldy #>STDSJ
|
|
jsr PUT_STRING
|
|
lda TMPINT
|
|
clc
|
|
adc #48
|
|
jsr PUTCHR
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
jmp GO_BAS
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; DSJ - Device Specified Jump (Internal Subroutine)
|
|
;;
|
|
DSJ: jsr TALK
|
|
lda #16 ;Get DSJ
|
|
sta ACBYTE
|
|
jsr SECTALK
|
|
@B: jsr QIN
|
|
lda ACBYTE
|
|
sta TMPINT
|
|
lda EFBYTE
|
|
beq @B
|
|
jsr UNTALK
|
|
rts
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; LISTEN Command 8 OpCode 2
|
|
;; _SEEK - Seek drive head to DISKNUM,CYLH,CYLL,HEAD,SECTOR
|
|
;;
|
|
_SEEK: lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
jsr CHRGET
|
|
jsr LOOKUP
|
|
jsr CHRGET
|
|
jsr PARSEDOS
|
|
|
|
lda DEVID
|
|
bne @HAVEDV
|
|
lda #$05
|
|
sta DEVID
|
|
@HAVEDV:jsr SEEK
|
|
jsr DSJ
|
|
lda TMPINT
|
|
beq @SKIPSTAT
|
|
lda #<STDSJ
|
|
ldy #>STDSJ
|
|
jsr PUT_STRING
|
|
|
|
lda TMPINT
|
|
clc
|
|
adc #48
|
|
jsr PUTCHR
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
|
|
jmp EXSTAT
|
|
@SKIPSTAT:
|
|
jmp GO_BAS
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; SEEK Seek drive head to D#,CYLH,CYLL,HEAD,SECTOR
|
|
;; (Internal Subroutine)
|
|
;;
|
|
SEEK: lda DEVID
|
|
jsr LISTEN
|
|
lda #8 ;Get DSJ
|
|
sta ACBYTE
|
|
jsr SECLIST
|
|
@B:
|
|
lda #'s'
|
|
jsr PUTCHR
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
|
|
lda #$02
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda DISKNUM
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda CYLH
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda CYLL
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda HEAD
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda SECTOR
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
jsr PPUNL
|
|
rts
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; _WRITE - Buffered Write to current seeked sector.
|
|
;;
|
|
_WRITE: lda #$00
|
|
sta A0BYTE
|
|
sta EFBYTE
|
|
jsr CHRGET
|
|
jsr LOOKUP
|
|
jsr CHRGET
|
|
jsr PARSEDOS
|
|
|
|
lda DEVID
|
|
bne @HAVEDV
|
|
lda #$05
|
|
sta DEVID
|
|
@HAVEDV:;jsr OWRITE
|
|
jsr DSJ
|
|
lda TMPINT
|
|
beq @SKIPSTAT
|
|
lda #<STDSJ
|
|
ldy #>STDSJ
|
|
jsr PUT_STRING
|
|
|
|
lda TMPINT
|
|
clc
|
|
adc #48
|
|
jsr PUTCHR
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
|
|
jmp EXSTAT
|
|
@SKIPSTAT:
|
|
jmp GO_BAS
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; OWRITE - OPEN Buffered Write to current seeked sector
|
|
;; (Internal Subroutine)
|
|
;; 256 Byte sectors must be written as a whole. (partial sectors filled with 00)
|
|
;;
|
|
OWRITE: jsr LISTEN
|
|
lda #9 ;Buffered Write
|
|
sta ACBYTE
|
|
jsr SECLIST
|
|
@B:
|
|
lda #'w'
|
|
jsr PUTCHR
|
|
lda #$0d
|
|
jsr PUTCHR
|
|
|
|
lda #$08
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
|
|
lda DISKNUM
|
|
sta ACBYTE
|
|
jsr QOUT
|
|
rts
|
|
|
|
; lda $fc ;
|
|
; pha
|
|
; lda $fb ; Start Address for write
|
|
; pha
|
|
|
|
; lda $ca ;
|
|
; pha
|
|
; lda $c9 ; End Address for write
|
|
; pha
|
|
|
|
; FIXME Buffer in 2 chunks of 128 bytes.
|
|
; OR 192 Bytes followed by 64 bytes? (It would be consistant
|
|
; with the way CBM did it)
|
|
; lda SECTOR
|
|
; sta ACBYTE
|
|
; jsr QOUT
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; CWRITE - CLOSE Buffered Write to current seeked sector
|
|
;; (Internal Subroutine)
|
|
;; 256 Byte sectors must be written as a whole. (partial sectors filled with 00)
|
|
;;
|
|
CWRITE:
|
|
jsr PPUNL
|
|
rts
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Using Accumulator to hold byte out
|
|
TALK: lda #$40
|
|
jmp TSKIP
|
|
LISTEN: lda #$20
|
|
TSKIP: sta ACBYTE
|
|
sta BTBYTE ;store variables
|
|
lda #$02
|
|
ora NRFDOUT
|
|
sta NRFDOUT ;NRFD high
|
|
lda #HIGH
|
|
sta NDACOUT ;NDAC high
|
|
lda A0BYTE
|
|
beq @NOEOI ;IF A0 = 0 branch
|
|
|
|
lda #LOW
|
|
sta EOIOUT ;EOI LOW
|
|
jsr IEEEOUT
|
|
lda #$00
|
|
sta A0BYTE
|
|
lda #HIGH
|
|
sta EOIOUT ;EOI HIGH
|
|
@NOEOI:
|
|
lda BTBYTE
|
|
ora DEVID
|
|
sta A5BYTE
|
|
lda #HIGH
|
|
sta DAVOUT
|
|
@DAVINCHK:
|
|
lda #$80
|
|
bit DAVIN
|
|
beq @DAVINCHK ;Wait for DAV HIGH
|
|
lda DAVIN
|
|
and #$fb
|
|
sta ATNOUT ;ATN LOW
|
|
|
|
; Write Byte with handshaking to IEEE Bus
|
|
; can't use x, y
|
|
IEEEOUT:
|
|
lda #HIGH
|
|
sta DAVOUT ;DAV OUT HIGH
|
|
lda NRFDIN
|
|
and #$41
|
|
cmp #$41 ;Does the device exist?
|
|
beq NODEVICE
|
|
lda A5BYTE
|
|
eor #$ff ;Invert bits (IEEE-488 is active low)
|
|
sta DATAOUT
|
|
NRFDCHK:
|
|
lda #$64
|
|
bit NRFDIN
|
|
beq NRFDCHK
|
|
lda #LOW
|
|
sta DAVOUT ;DAV OUT LOW
|
|
UNKCHK: lda #$01
|
|
bit NRFDIN
|
|
beq UNKCHK ;This is in the BASIC source Why?
|
|
lda #HIGH
|
|
sta DAVOUT ;DAV OUT HIGH
|
|
lda #$ff
|
|
sta DATAOUT ;DATA high
|
|
rts
|
|
|
|
NODEVICE:
|
|
lda #<DEVNF
|
|
ldy #>DEVNF
|
|
jsr PUT_STRING
|
|
jmp GO_BAS
|
|
|
|
; Send Secondary Listen Address
|
|
SECLIST:
|
|
lda ACBYTE
|
|
ora #96
|
|
sta ACBYTE ;FIXME Need to save this?
|
|
sta A5BYTE
|
|
jsr IEEEOUT
|
|
ATNHI: lda ATNOUT
|
|
ora #$04
|
|
sta ATNOUT
|
|
rts
|
|
|
|
; Send Secondary Talk Address
|
|
SECTALK:
|
|
lda ACBYTE
|
|
ora #96
|
|
sta ACBYTE
|
|
sta A5BYTE
|
|
jsr IEEEOUT
|
|
lda NRFDOUT
|
|
and #$fd
|
|
sta NRFDOUT ;NRFD OUT LOW
|
|
lda #LOW
|
|
sta NDACOUT ;NDAC OUT LOW
|
|
jmp ATNHI
|
|
|
|
;Send untalk command
|
|
UNTALK: lda ATNOUT
|
|
and #$fb
|
|
sta ATNOUT ;ATN OUT HIGH
|
|
lda #$5f
|
|
jsr TSKIP
|
|
jmp ATNHI
|
|
|
|
; Write queued bytes to IEEE BUS
|
|
; can't use x, y
|
|
QOUT: lda A0BYTE
|
|
and #$80
|
|
bne A0MAXED
|
|
lda A0BYTE
|
|
sec
|
|
sbc #$01
|
|
sta A0BYTE
|
|
bmi QBYTE
|
|
lda #$ff
|
|
sta A0BYTE
|
|
jmp QBYTE
|
|
A0MAXED:
|
|
; lda ACBYTE
|
|
;sta BYBYTE
|
|
jsr IEEEOUT
|
|
;lda BYBYTE
|
|
;sta ACBYTE
|
|
QBYTE: lda ACBYTE
|
|
sta A5BYTE
|
|
rts
|
|
|
|
; Read from the IEEE BUS
|
|
QIN:
|
|
lda #HIGH
|
|
sta DAVOUT
|
|
|
|
lda #LOW
|
|
sta NDACOUT
|
|
lda NRFDOUT
|
|
ora #$02
|
|
sta NRFDOUT ;NRFD OUT HIGH
|
|
@B1: lda DAVIN
|
|
and #$80
|
|
bne @B1 ;Wait for DAV LOW.
|
|
lda NRFDOUT
|
|
and #$fd
|
|
sta NRFDOUT ;NRFD OUT LOW
|
|
lda #$40
|
|
bit EOIIN
|
|
bne @F
|
|
lda EFBYTE
|
|
ora #$40
|
|
sta EFBYTE
|
|
@F:
|
|
lda #$ff
|
|
sec
|
|
sbc DATAIN
|
|
sta ACBYTE
|
|
;sta BYBYTE
|
|
lda #HIGH
|
|
sta NDACOUT
|
|
@B2: lda #$80
|
|
bit DAVIN
|
|
beq @B2 ;Wait for DAV HIGH
|
|
lda #LOW
|
|
sta NDACOUT
|
|
rts
|
|
|
|
; UNLISTEN With Parallel Polling.
|
|
PPUNL: lda #63
|
|
sta ACBYTE
|
|
sta BTBYTE
|
|
lda NRFDOUT
|
|
ora #$02
|
|
sta NRFDOUT ;NRFD high
|
|
lda #HIGH
|
|
sta NDACOUT ;NDAC high
|
|
lda A0BYTE
|
|
cmp #$00
|
|
beq @F
|
|
lda #LOW
|
|
sta EOIOUT ;EOI LOW
|
|
jsr IEEEOUT
|
|
lda #HIGH
|
|
sta EOIOUT ;EOI HIGH
|
|
lda #$00
|
|
sta A0BYTE
|
|
@F: lda BTBYTE
|
|
ora DEVID
|
|
sta A5BYTE
|
|
lda #HIGH
|
|
sta DAVOUT
|
|
@B: lda DAVIN
|
|
and #$80
|
|
beq @B ;Wait for DAV HIGH
|
|
CHKPOLL:
|
|
lda #LOW
|
|
sta EOIOUT ;EOI LOW
|
|
lda ATNOUT
|
|
and #$fb
|
|
sta ATNOUT ;ATN LOW (EOI + ATN = Parallel Poll)
|
|
ldx #$06
|
|
jsr JIFDLY
|
|
ldy DATAIN ;Y Holds the POLL
|
|
lda #HIGH
|
|
sta EOIOUT ;EOI HIGH
|
|
lda ATNOUT
|
|
ora #$04
|
|
sta ATNOUT ;ATN HIGH
|
|
lda #$08
|
|
sec
|
|
sbc DEVID
|
|
tax
|
|
lda #$00
|
|
sec
|
|
@B: rol
|
|
dex
|
|
bne @B ;HP-IB devices respond to poll on DIO# = 8 - device ID
|
|
sta TMPINT
|
|
tya
|
|
and TMPINT
|
|
bne CHKPOLL
|
|
lda ATNOUT
|
|
and #$fb
|
|
sta ATNOUT
|
|
jsr IEEEOUT
|
|
jmp ATNHI
|
|
|
|
|
|
; X = # delay loops
|
|
JIFDLY: lda $8f
|
|
@B: cmp $8f
|
|
beq @B
|
|
dex
|
|
bne JIFDLY
|
|
rts
|
|
|
|
;
|
|
; Matthew Hudson Copyright
|
|
;
|
|
CPYRT: .byte "(c) 2009 matthew a hudson"
|
|
.byte $0D
|
|
.byte $00
|
|
DEVNF: .byte "device not found!"
|
|
.byte $0D
|
|
.byte $00
|
|
.end
|