diff --git a/AMIGODOSREL.ASM b/AMIGODOSREL.ASM new file mode 100644 index 0000000..a8aa2a1 --- /dev/null +++ b/AMIGODOSREL.ASM @@ -0,0 +1,1250 @@ +; +; 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 ; 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 #(_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 + jsr PUT_STRING + lda TMPTR1 + jsr PRTHEX + lda TMPTR1+1 + jsr PRTHEX + lda #$0d + jsr PUTCHR + + lda #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 + 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 + 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 + 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 + 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