Initial working PiDrive
This commit is contained in:
parent
d8bf70b34d
commit
bf07a8c365
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
<20>ゥL<>
|
|
@ -0,0 +1,2 @@
|
|||
LIST
|
||||
]
|
Binary file not shown.
|
@ -0,0 +1,32 @@
|
|||
NEW
|
||||
|
||||
REM LOAD PIDRIVE AND APPLY FIXUPS
|
||||
|
||||
300 PRINT CHR$ (4);"BLOAD PIDRIVE.A2DRVR"
|
||||
310 VE = 816 : FX = VE + 4 : SI = PEEK(768) : SN = SI / 8
|
||||
|
||||
REM CHECK IF PRODOS DEVICE VECTOR SET
|
||||
|
||||
320 IF PEEK(48913 + SN) = 222 THEN POKE 48912 + SN, PEEK(VE) : POKE 48913 + SN, PEEK (VE + 1)
|
||||
330 IF PEEK(48929 + SN) = 222 THEN POKE 48928 + SN, PEEK(VE) : POKE 48929 + SN, PEEK (VE + 1)
|
||||
340 FOR D = 48946 TO 48959
|
||||
350 IF PEEK (D) = 0 THEN POKE D, SI + 1 : POKE 48945, PEEK (48945) + 1 : D = 48960
|
||||
360 NEXT
|
||||
370 FOR D = 48946 TO 48959
|
||||
380 IF PEEK (D) = 0 THEN POKE D, SI + 1 : POKE 48945, PEEK (48945) + 129 : D = 48960
|
||||
390 NEXT
|
||||
395 PRINT "PIDRIVE CONNECTED ON SLOT #"; SN / 2
|
||||
|
||||
REM INSERT CLOCK DRIVER
|
||||
|
||||
400 POKE 48903, PEEK (VE + 2) : POKE 48904, PEEK (VE + 3)
|
||||
405 PRINT "PICLOCK CONNECTED"
|
||||
|
||||
REM RUN THROUGH FIXUP TABLE
|
||||
|
||||
410 AA = PEEK (FX) : IF AA = 0 THEN NEW : END
|
||||
420 AA = AA + PEEK (FX + 1) * 256 : FX = FX + 2
|
||||
430 POKE AA, PEEK (AA) + SI
|
||||
440 GOTO 410
|
||||
|
||||
]
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,66 @@
|
|||
NEW
|
||||
|
||||
10 PRINT
|
||||
11 PRINT "STARTING APPLE II PI CLIENT."
|
||||
12 PRINT "PRESS ANY KEY TO CANCEL..."
|
||||
|
||||
REM ALLOCATE BASIC BUFFER SPACE
|
||||
|
||||
20 PRINT CHR$ (4);"BLOAD DEFSLOT"
|
||||
30 CALL 769
|
||||
|
||||
REM LOAD APPROPRIATE CLIENT
|
||||
|
||||
40 A2$ = "A2PI" : IF PEEK (64435) < > 6 THEN A2$ = "A2PLUSPI"
|
||||
50 PRINT CHR$ (4);"BLOAD ";A2$
|
||||
|
||||
REM IF DEFAULT SLOT NOT SET, SEARCH FOR SSC
|
||||
|
||||
60 IF PEEK (768) = 0 THEN GOSUB 100
|
||||
65 POKE 769,0
|
||||
|
||||
REM INIT A2PI DRIVER
|
||||
|
||||
70 PRINT CHR$ (4);"PR# A$9600"
|
||||
80 IF PEEK (769) < > 0 THEN PRINT "APPLE II PI CONNECTED." : PRINT "KEYBOARD ROUTED TO LINUX" : GOSUB 300
|
||||
90 NEW : END
|
||||
|
||||
REM SEARCH FOR SSC
|
||||
|
||||
100 SC = 0 : PI = 0
|
||||
110 FOR S = 1 TO 7
|
||||
120 FW = 49152 + 256 * S
|
||||
130 IF PEEK (FW + 5) = 56 AND PEEK (FW + 7) = 24 AND PEEK (FW + 12) = 49 THEN SC = S : PRINT "FOUND SERIAL CARD: SLOT #";S
|
||||
150 NEXT
|
||||
160 IF SC < > 0 THEN POKE 768,SC * 16: RETURN
|
||||
|
||||
REM NOTHING FOUND. LOW BUZZ TO SIGNIFY CONFIG NEEDED
|
||||
|
||||
200 FOR S = 1 TO 100 : SP = PEEK (49200): NEXT
|
||||
210 POP : PRINT CHR$ (4);"RUN CONFIG"
|
||||
220 END
|
||||
|
||||
REM LOAD PIDRIVE AND APPLY FIXUPS
|
||||
|
||||
300 PRINT CHR$ (4);"BLOAD PIDRIVE"
|
||||
310 VE = 816 : FX = VE + 4 : SI = PEEK(768) : SN = SI / 8
|
||||
|
||||
REM CHECK IF PRODOS DEVICE VECTOR SET
|
||||
|
||||
320 IF PEEK(48913 + SN) = 222 THEN POKE 48912 + SN, PEEK(VE) : POKE 48913 + SN, PEEK (VE + 1)
|
||||
330 IF PEEK(48929 + SN) = 222 THEN POKE 48928 + SN, PEEK(VE) : POKE 48929 + SN, PEEK (VE + 1)
|
||||
335 PRINT "PIDRIVE CONNECTED ON SLOT #"; SN / 2
|
||||
|
||||
REM INSERT CLOCK DRIVER
|
||||
|
||||
340 POKE 48903 + SN, PEEK (VE + 2) : POKE 48904 + SN, PEEK (VE + 3)
|
||||
345 PRINT "PICLOCK CONNECTED"
|
||||
|
||||
REM RUN THROUGH FIXUP TABLE
|
||||
|
||||
350 AA = PEEK (FX) + PEEK (FX + 1) * 256 : FX = FX + 2
|
||||
360 IF AA = 0 THEN RETURN
|
||||
370 POKE AA, PEEK (AA) + SI
|
||||
380 GOTO 350
|
||||
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
MEMORY {
|
||||
RAM: start = $2000, size = $200, file = %O;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load = RAM, type = rw;
|
||||
DATA: load = RAM, type = rw;
|
||||
BSS: load = RAM, type = rw;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
.SUFFIXES =
|
||||
AFLAGS = -o $@
|
||||
ROM = ROM\#062000
|
||||
DRVR = PIDRIVE\#062000
|
||||
#
|
||||
# Image filetypes for CiderPress
|
||||
#
|
||||
PLATYPE = \#ed0000
|
||||
BINTYPE = \#060000
|
||||
SYSTYPE = \#ff0000
|
||||
TXTTYPE = \#040000
|
||||
|
||||
all: $(ROM) $(DRVR)
|
||||
|
||||
$(ROM): rom.s
|
||||
ca65 rom.s -o rom.o
|
||||
ld65 -o $(ROM) -C rom.cfg rom.o
|
||||
|
||||
$(DRVR): pidrive.s
|
||||
ca65 pidrive.s -o pidrive.o
|
||||
ld65 -o $(DRVR) -C drvr.cfg pidrive.o
|
|
@ -0,0 +1,280 @@
|
|||
.DEFINE EQU =
|
||||
.DEFINE DB .BYTE
|
||||
.DEFINE DW .WORD
|
||||
.CODE
|
||||
PISLOT EQU $00
|
||||
;*
|
||||
;* ACIA REGISTERS
|
||||
;*
|
||||
ACIADR EQU $C088+PISLOT*16
|
||||
ACIASR EQU $C089+PISLOT*16
|
||||
ACIACR EQU $C08A+PISLOT*16
|
||||
ACIAMR EQU $C08B+PISLOT*16
|
||||
;*
|
||||
;* APPLE I/O LOCATIONS
|
||||
;*
|
||||
KEYBD EQU $C000
|
||||
STROBE EQU $C010
|
||||
;*
|
||||
;* UTIL ROUTINES
|
||||
;*
|
||||
WAIT EQU $FCA8
|
||||
COUT EQU $FDED
|
||||
CROUT EQU $FD8E
|
||||
PRBYTE EQU $FDDA
|
||||
PRHEX EQU $FDE3
|
||||
PRNTAX EQU $F941
|
||||
RDKEY EQU $FD0C
|
||||
RDCHAR EQU $FD35
|
||||
GETLN EQU $FD6A
|
||||
;*
|
||||
;* ZERO PAGE PARAMETERS
|
||||
;*
|
||||
PDCMD EQU $42
|
||||
PDUNIT EQU $43
|
||||
PDBUFF EQU $44
|
||||
PDBUFL EQU $44
|
||||
PDBUFH EQU $45
|
||||
PDBLKL EQU $46
|
||||
PDBLKH EQU $47
|
||||
;*
|
||||
;* SLOT INDEX = SLOT # * 16
|
||||
;*
|
||||
SLOTIDX EQU $0300
|
||||
;*
|
||||
;* DRIVER SCRATCHPAD
|
||||
;*
|
||||
TMP EQU $0478+PISLOT
|
||||
PAD0 EQU $0478+PISLOT
|
||||
PAD1 EQU $04F8+PISLOT
|
||||
PAD2 EQU $0578+PISLOT
|
||||
PAD3 EQU $05F8+PISLOT
|
||||
PAD4 EQU $0678+PISLOT
|
||||
PAD5 EQU $06F8+PISLOT
|
||||
PAD6 EQU $0778+PISLOT
|
||||
PAD7 EQU $07F8+PISLOT
|
||||
;*
|
||||
;* PRODOS COMMANDS
|
||||
;*
|
||||
PDSTAT EQU 0
|
||||
PDREAD EQU 1
|
||||
PDWRITE EQU 2
|
||||
PDFORMT EQU 3
|
||||
;*
|
||||
;* PRODOS ERRORS
|
||||
;*
|
||||
PDNOERR EQU $00
|
||||
PDIOERR EQU $27
|
||||
PDNODEV EQU $28
|
||||
PDWRPRT EQU $2B
|
||||
;*
|
||||
;* PRODOS GLOBAL PAGE LOCATIONS
|
||||
;*
|
||||
CLKJSR EQU $BF06
|
||||
DEV1L EQU $BF10
|
||||
DEV1H EQU $BF11
|
||||
DEV2L EQU $BF20
|
||||
DEV2H EQU $BF21
|
||||
DEVCNT EQU $BF31
|
||||
DEVLST EQU $BF32
|
||||
PDTIME EQU $BF90
|
||||
;*
|
||||
;* ZERO PAGE LOCATIONS FOR LOADER
|
||||
;*
|
||||
DSTPTR EQU $06
|
||||
DSTL EQU $06
|
||||
DSTH EQU $07
|
||||
SRCPTR EQU $08
|
||||
SRCL EQU $08
|
||||
SRCH EQU $09
|
||||
;*
|
||||
;* DRIVER LOADER
|
||||
;*
|
||||
DRVRDST EQU $D742
|
||||
DRVRLEN EQU 125
|
||||
LDA #$60
|
||||
STA CLKJSR ; UNHOOK CLOCK DRIVER (WITH RTS)
|
||||
LDA #<DRVRELOC
|
||||
STA SRCL
|
||||
LDA #>DRVRELOC
|
||||
STA SRCH
|
||||
LDA #<DRVRDST
|
||||
STA DSTL
|
||||
LDA #>DRVRDST
|
||||
STA DSTH
|
||||
LDY #DRVRLEN-1
|
||||
BIT $C08B ; ENABLE LCRAM & WRITE
|
||||
BIT $C08B
|
||||
CPYLP: LDA (SRCPTR),Y
|
||||
STA (DSTPTR),Y
|
||||
DEY
|
||||
BPL CPYLP
|
||||
INY
|
||||
LDX #SFIXUPTBL-IFIXUPTBL-1
|
||||
IFIXLP: LDA IFIXUPTBL,X
|
||||
STA DSTH
|
||||
DEX
|
||||
LDA IFIXUPTBL,X
|
||||
STA DSTL
|
||||
LDA (DSTPTR),Y
|
||||
ORA SLOTIDX
|
||||
STA (DSTPTR),Y
|
||||
DEX
|
||||
BPL IFIXLP
|
||||
LDX #DRVRELOC-SFIXUPTBL-1
|
||||
SFIXLP: LDA SFIXUPTBL,X
|
||||
STA DSTH
|
||||
DEX
|
||||
LDA SFIXUPTBL,X
|
||||
STA DSTL
|
||||
LDA SLOTIDX
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
CLC
|
||||
ADC (DSTPTR),Y
|
||||
STA (DSTPTR),Y
|
||||
DEX
|
||||
BPL SFIXLP
|
||||
BIT $C08A ; EBABLE ROM
|
||||
LDA SLOTIDX
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
TAX
|
||||
LDA DEV1H,X
|
||||
CMP #$DE ; GNODEV
|
||||
BNE INSDEV2
|
||||
LDA #<DRVRDST
|
||||
STA DEV1L,X
|
||||
LDA #>DRVRDST
|
||||
STA DEV1H,X
|
||||
INY
|
||||
INSDEV2:
|
||||
LDA DEV2H,X
|
||||
CMP #$DE
|
||||
BNE INCDEV1
|
||||
LDA #<DRVRDST
|
||||
STA DEV2L,X
|
||||
LDA #>DRVRDST
|
||||
STA DEV2H,X
|
||||
INY
|
||||
INCDEV1:
|
||||
CPY #$00
|
||||
BEQ EXIT ; NOTHING TO BE DONE HERE
|
||||
LDX #$00
|
||||
DEV1LP: LDA DEVLST,X
|
||||
BNE NXTDEV1
|
||||
LDA SLOTIDX
|
||||
ORA #$01
|
||||
STA DEVLST,X
|
||||
INC DEVCNT
|
||||
BNE INCDEV2
|
||||
NXTDEV1:
|
||||
INX
|
||||
CPX #14
|
||||
BNE DEV1LP
|
||||
INCDEV2:
|
||||
LDX #$00
|
||||
DEV2LP: LDA DEVLST,X
|
||||
BNE NXTDEV2
|
||||
LDA SLOTIDX
|
||||
ORA #$81
|
||||
STA DEVLST,X
|
||||
INC DEVCNT
|
||||
BNE EXIT
|
||||
NXTDEV2:
|
||||
INX
|
||||
CPX #14
|
||||
BNE DEV2LP
|
||||
EXIT: RTS
|
||||
;*
|
||||
;* FIXUP TABLE
|
||||
;*
|
||||
IFIXUPTBL:
|
||||
DW FIXUP1+1
|
||||
DW FIXUP2+1
|
||||
DW FIXUP3+1
|
||||
DW FIXUP4+1
|
||||
SFIXUPTBL:
|
||||
DW FIXUP5+1
|
||||
DW FIXUP6+1
|
||||
DRVRELOC:
|
||||
;*
|
||||
;* PRODOS INTELLIGENT DEVICE ENTRYPOINT (OVERWRITE CLOCK DRIVER)
|
||||
;*
|
||||
.ORG DRVRDST
|
||||
DOCMD: LDA PDUNIT
|
||||
ASL
|
||||
LDA PDCMD
|
||||
ROL
|
||||
ASL
|
||||
ORA #$A0
|
||||
LDX PDBLKL
|
||||
LDY PDBLKH
|
||||
PHP
|
||||
FIXUP5: STA PAD0
|
||||
SEI
|
||||
JSR SENDACC
|
||||
TXA
|
||||
JSR SENDACC
|
||||
TYA
|
||||
JSR SENDACC
|
||||
CHKACK: JSR RECVACC
|
||||
TAX
|
||||
DEX
|
||||
FIXUP6: CPX PAD0
|
||||
BNE CHKACK
|
||||
LDY PDCMD
|
||||
BEQ STATUS
|
||||
LDX #$02 ; # OF PAGES TO XFER
|
||||
DEY ; CPY #PDREAD
|
||||
BEQ RDBLK
|
||||
DEY ; CMP #PDWRITE
|
||||
BEQ WRBLK
|
||||
IOERR: LDA #PDIOERR
|
||||
CMDERR: PLP
|
||||
SEC
|
||||
DOCLK: RTS ; NO OP CLOCK ROUTINE
|
||||
RDBLK: JSR RECVACC
|
||||
STA (PDBUFF),Y
|
||||
INY
|
||||
BNE RDBLK
|
||||
INC PDBUFH
|
||||
DEX
|
||||
BNE RDBLK
|
||||
STATUS: LDX #$FF
|
||||
DEY ; LDY #$FF
|
||||
CMDEX: JSR RECVACC
|
||||
BNE CMDERR
|
||||
PLP
|
||||
CLC
|
||||
RTS
|
||||
WRBLK: LDA (PDBUFF),Y
|
||||
JSR SENDACC
|
||||
INY
|
||||
BNE WRBLK
|
||||
INC PDBUFH
|
||||
DEX
|
||||
BNE WRBLK
|
||||
BEQ CMDEX
|
||||
;*
|
||||
;* ACIA I/O ROUTINES
|
||||
;*
|
||||
SENDACC:
|
||||
PHA
|
||||
FIXUP1:
|
||||
SENDWT: LDA ACIASR
|
||||
AND #$10
|
||||
BEQ SENDWT
|
||||
PLA
|
||||
FIXUP2: STA ACIADR
|
||||
RTS
|
||||
RECVACC:
|
||||
FIXUP3:
|
||||
RECVWT: LDA ACIASR
|
||||
AND #$08
|
||||
BEQ RECVWT
|
||||
FIXUP4: LDA ACIADR
|
||||
RTS
|
|
@ -0,0 +1,172 @@
|
|||
.DEFINE EQU =
|
||||
.DEFINE DB .BYTE
|
||||
.DEFINE DW .WORD
|
||||
.CODE
|
||||
PISLOT EQU $00
|
||||
;*
|
||||
;* ACIA REGISTERS
|
||||
;*
|
||||
ACIADR EQU $C088+PISLOT*16
|
||||
ACIASR EQU $C089+PISLOT*16
|
||||
ACIACR EQU $C08A+PISLOT*16
|
||||
ACIAMR EQU $C08B+PISLOT*16
|
||||
;*
|
||||
;* APPLE I/O LOCATIONS
|
||||
;*
|
||||
KEYBD EQU $C000
|
||||
STROBE EQU $C010
|
||||
;*
|
||||
;* UTIL ROUTINES
|
||||
;*
|
||||
WAIT EQU $FCA8
|
||||
COUT EQU $FDED
|
||||
CROUT EQU $FD8E
|
||||
PRBYTE EQU $FDDA
|
||||
PRHEX EQU $FDE3
|
||||
PRNTAX EQU $F941
|
||||
RDKEY EQU $FD0C
|
||||
RDCHAR EQU $FD35
|
||||
GETLN EQU $FD6A
|
||||
;*
|
||||
;* ZERO PAGE PARAMETERS
|
||||
;*
|
||||
PDCMD EQU $42
|
||||
PDUNIT EQU $43
|
||||
PDBUFF EQU $44
|
||||
PDBUFL EQU $44
|
||||
PDBUFH EQU $45
|
||||
PDBLKL EQU $46
|
||||
PDBLKH EQU $47
|
||||
;*
|
||||
;* DRIVER SCRATCHPAD
|
||||
;*
|
||||
TMP EQU $0478+PISLOT
|
||||
PAD0 EQU $0478+PISLOT
|
||||
PAD1 EQU $04F8+PISLOT
|
||||
PAD2 EQU $0578+PISLOT
|
||||
PAD3 EQU $05F8+PISLOT
|
||||
PAD4 EQU $0678+PISLOT
|
||||
PAD5 EQU $06F8+PISLOT
|
||||
PAD6 EQU $0778+PISLOT
|
||||
PAD7 EQU $07F8+PISLOT
|
||||
;*
|
||||
;* PRODOS COMMANDS
|
||||
;*
|
||||
PDSTAT EQU 0
|
||||
PDREAD EQU 1
|
||||
PDWRITE EQU 2
|
||||
PDFORMT EQU 3
|
||||
;*
|
||||
;* PRODOS ERRORS
|
||||
;*
|
||||
PDNOERR EQU $00
|
||||
PDIOERR EQU $27
|
||||
PDNODEV EQU $28
|
||||
PDWRPRT EQU $2B
|
||||
;*
|
||||
;* PRODOS GLOBAL PAGE LOCATIONS
|
||||
;*
|
||||
PDTIME EQU $BF90
|
||||
;*
|
||||
;* VECTORS
|
||||
;*
|
||||
;VECTBL: DB >DOCMD
|
||||
; DB >DOCLK
|
||||
; DB >FIXUP1+1
|
||||
; DB >FIXUP2+1
|
||||
; DB >FIXUP3+1
|
||||
; DB >FIXUP4+1
|
||||
;TMP: DB 0
|
||||
;*
|
||||
;* PRODOS INTELLIGENT DEVICE ENTRYPOINT
|
||||
;*
|
||||
DOCMD: LDA PDUNIT
|
||||
ASL
|
||||
LDA PDCMD
|
||||
ROL
|
||||
ASL
|
||||
ORA #$A0
|
||||
LDX PDBLKL
|
||||
LDY PDBLKH
|
||||
PHP
|
||||
JSR SENDCMD
|
||||
LDY PDCMD
|
||||
BEQ STATUS
|
||||
LDX #$02 ; # OF PAGES TO XFER
|
||||
DEY ; CPY #PDREAD
|
||||
BEQ RDBLK
|
||||
DEY ; CMP #PDWRITE
|
||||
BEQ WRBLK
|
||||
IOERR: LDA #PDIOERR
|
||||
CMDERR: PLP
|
||||
SEC
|
||||
RTS
|
||||
RDBLK: JSR RECVACC
|
||||
STA (PDBUFF),Y
|
||||
INY
|
||||
BNE RDBLK
|
||||
INC PDBUFH
|
||||
DEX
|
||||
BNE RDBLK
|
||||
STATUS: LDX #$FF
|
||||
DEY ; LDY #$FF
|
||||
CMDEX: JSR RECVACC
|
||||
BNE CMDERR
|
||||
PLP
|
||||
CLC
|
||||
RTS
|
||||
WRBLK: LDA (PDBUFF),Y
|
||||
JSR SENDACC
|
||||
INY
|
||||
BNE WRBLK
|
||||
INC PDBUFH
|
||||
DEX
|
||||
BNE WRBLK
|
||||
BEQ CMDEX
|
||||
;*
|
||||
;* PRODOS CLOCK ROUTINE
|
||||
;*
|
||||
;DOCLK: LDA #$AC
|
||||
; PHP
|
||||
; JSR SENDCMD
|
||||
; LDY #$00
|
||||
;CLKLP: JSR RECVACC
|
||||
; STA PDTIME,Y
|
||||
; INY
|
||||
; CPY #$04
|
||||
; BNE CLKLP
|
||||
; PLP
|
||||
; RTS
|
||||
;*
|
||||
;* ACIA I/O ROUTINES
|
||||
;*
|
||||
SENDCMD:
|
||||
STA TMP
|
||||
SEI
|
||||
JSR SENDACC
|
||||
TXA
|
||||
JSR SENDACC
|
||||
TYA
|
||||
JSR SENDACC
|
||||
CHKACK: JSR RECVACC
|
||||
TAX
|
||||
DEX
|
||||
CPX TMP
|
||||
BNE CHKACK
|
||||
GOTACK: RTS
|
||||
SENDACC:
|
||||
PHA
|
||||
FIXUP1:
|
||||
SENDWT: LDA ACIASR
|
||||
AND #$10
|
||||
BEQ SENDWT
|
||||
PLA
|
||||
FIXUP2: STA ACIADR
|
||||
RTS
|
||||
RECVACC:
|
||||
FIXUP3:
|
||||
RECVWT: LDA ACIASR
|
||||
AND #$08
|
||||
BEQ RECVWT
|
||||
FIXUP4: LDA ACIADR
|
||||
RTS
|
|
@ -0,0 +1,10 @@
|
|||
MEMORY {
|
||||
ROM: start = $c700, size = $100, file = %O;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load = ROM, type = ro;
|
||||
DATA: load = ROM, type = ro;
|
||||
BSS: load = ROM, type = ro;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
.DEFINE EQU =
|
||||
.CODE
|
||||
PISLOT EQU $05
|
||||
;*
|
||||
;* ACIA REGISTERS
|
||||
;*
|
||||
ACIADR EQU $C088+PISLOT*16
|
||||
ACIASR EQU $C089+PISLOT*16
|
||||
ACIACR EQU $C08A+PISLOT*16
|
||||
ACIAMR EQU $C08B+PISLOT*16
|
||||
;*
|
||||
;* APPLE I/O LOCATIONS
|
||||
;*
|
||||
KEYBD EQU $C000
|
||||
STROBE EQU $C010
|
||||
;*
|
||||
;* UTIL ROUTINES
|
||||
;*
|
||||
WAIT EQU $FCA8
|
||||
COUT EQU $FDED
|
||||
CROUT EQU $FD8E
|
||||
PRBYTE EQU $FDDA
|
||||
PRHEX EQU $FDE3
|
||||
PRNTAX EQU $F941
|
||||
RDKEY EQU $FD0C
|
||||
RDCHAR EQU $FD35
|
||||
GETLN EQU $FD6A
|
||||
;*
|
||||
;* ZERO PAGE PARAMETERS
|
||||
;*
|
||||
PDCMD EQU $42
|
||||
PDUNIT EQU $43
|
||||
PDBUFF EQU $44
|
||||
PDBUFL EQU $44
|
||||
PDBUFH EQU $45
|
||||
PDBLKL EQU $46
|
||||
PDBLKH EQU $47
|
||||
;*
|
||||
;* PRODOS COMMANDS
|
||||
;*
|
||||
PDSTAT EQU 0
|
||||
PDREAD EQU 1
|
||||
PDWRITE EQU 2
|
||||
PDFORMT EQU 3
|
||||
;*
|
||||
;* PRODOS ERRORS
|
||||
;*
|
||||
PDNOERR EQU $00
|
||||
PDIOERR EQU $27
|
||||
PDNODEV EQU $28
|
||||
PDWRPRT EQU $2B
|
||||
;*
|
||||
;* AUTOSTART BOOT SIGNATURE
|
||||
;*
|
||||
LDX #$20
|
||||
LDY #$00
|
||||
LDX #$03
|
||||
STX $3C
|
||||
;*
|
||||
;* INIT ACIA
|
||||
;*
|
||||
STY ACIASR ; RESET STATUS REGISTER
|
||||
LDY #$0B
|
||||
STY ACIACR ; SET CONTROL REGISTER
|
||||
LDY #$10
|
||||
STY ACIAMR ; SET COMMAND REGISTER (115K BAUD)
|
||||
;*
|
||||
;* SYNC WITH HOST
|
||||
;*
|
||||
SYNC: LDA #$80
|
||||
STA ACIADR
|
||||
LDA #$FF
|
||||
JSR WAIT
|
||||
LDA KEYBD
|
||||
BMI SKIPBOOT
|
||||
LDA ACIASR
|
||||
AND #$08
|
||||
BEQ SYNC
|
||||
LDA ACIADR
|
||||
CMP #$81
|
||||
BNE SYNC
|
||||
BEQ BOOT
|
||||
SKIPBOOT: STA STROBE
|
||||
JMP $FABA ; JUMP BACK TO BOOT SCANNER ROM ROUTINE
|
||||
;*
|
||||
;* CREATE COMMAND BUFFER FOR BOOT BLOCK
|
||||
;*
|
||||
BOOT: LDA #PDREAD
|
||||
STA PDCMD
|
||||
LDA #$00
|
||||
STA PDUNIT
|
||||
STA PDBUFL
|
||||
STA PDBLKL
|
||||
STA PDBLKH
|
||||
PHA
|
||||
LDA #$08
|
||||
STA PDBUFH
|
||||
PHA
|
||||
;*
|
||||
;* PRODOS INTELLIGENT DEVICE ENTRYPOINT
|
||||
;*
|
||||
DOCMD: PHP
|
||||
SEI
|
||||
LDA PDUNIT
|
||||
ASL
|
||||
LDA PDCMD
|
||||
ROL
|
||||
ASL
|
||||
JSR SENDACC
|
||||
LDA PDBLKL
|
||||
JSR SENDACC
|
||||
LDA PDBLKH
|
||||
JSR SENDACC
|
||||
CHKACK: JSR RECVACC
|
||||
TAX
|
||||
DEX
|
||||
CPX PDCMD
|
||||
BNE CHKACK
|
||||
LDY #$00
|
||||
CPX #PDREAD
|
||||
BEQ RDBLK
|
||||
CPX #PDWRITE
|
||||
BEQ WRBLK
|
||||
CPX #PDSTAT
|
||||
BEQ STATDEV
|
||||
LDA #PDIOERR
|
||||
CMDERR: PLP
|
||||
SEC
|
||||
RTS
|
||||
STATDEV:
|
||||
LDX #$FF
|
||||
LDY #$FF
|
||||
CMDEX: JSR RECVACC
|
||||
BNE CMDERR
|
||||
PLP
|
||||
CLC
|
||||
RTS
|
||||
RDBLK:
|
||||
RD1BLK: JSR RECVACC
|
||||
STA (PDBUFF),Y
|
||||
INY
|
||||
BNE RD1BLK
|
||||
INC PDBUFH
|
||||
RD2BLK: JSR RECVACC
|
||||
STA (PDBUFF),Y
|
||||
INY
|
||||
BNE RD2BLK
|
||||
BEQ CMDEX
|
||||
WRBLK:
|
||||
WR1BLK: LDA (PDBUFF),Y
|
||||
JSR SENDACC
|
||||
INY
|
||||
BNE WR1BLK
|
||||
INC PDBUFH
|
||||
WR2BLK: LDA (PDBUFF),Y
|
||||
JSR SENDACC
|
||||
INY
|
||||
BNE WR1BLK
|
||||
BEQ CMDEX
|
||||
SENDACC:
|
||||
PHA
|
||||
SENDWT: LDA ACIASR
|
||||
AND #$10
|
||||
BEQ SENDWT
|
||||
PLA
|
||||
STA ACIADR
|
||||
RTS
|
||||
RECVACC:
|
||||
RECVWT: LDA ACIASR
|
||||
AND #$08
|
||||
BEQ RECVWT
|
||||
LDA ACIADR
|
||||
RTS
|
Binary file not shown.
|
@ -12,8 +12,8 @@
|
|||
struct timespec tv;
|
||||
struct input_event evkey, evabsx, evabsy, evsync;
|
||||
#define BTTN_IO 0xC061
|
||||
#define READGP0 0x380
|
||||
#define READGP1 0x388
|
||||
#define READGP0 0x320
|
||||
#define READGP1 0x328
|
||||
char readgp[] = {
|
||||
0xA2, 0x00, // LDX #PADDLE
|
||||
0x78, // SEI
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
struct timespec tv;
|
||||
struct input_event evkey, evrelx, evrely, evsync;
|
||||
#define BTTN_IO 0xC061
|
||||
#define READGP0 0x380
|
||||
#define READGP1 0x388
|
||||
#define READGP0 0x320
|
||||
#define READGP1 0x328
|
||||
char readgp[] = {
|
||||
0xA2, 0x00, // LDX #PADDLE
|
||||
0x78, // SEI
|
||||
|
|
|
@ -14,8 +14,8 @@ struct input_event evkey, evrelx, evrely, evsync;
|
|||
#define PEN_UP 0
|
||||
#define PEN_DOWN 1
|
||||
#define BTTN_IO 0xC061
|
||||
#define READGP0 0x380
|
||||
#define READGP1 0x388
|
||||
#define READGP0 0x320
|
||||
#define READGP1 0x328
|
||||
char readgp[] = {
|
||||
0xA2, 0x00, // LDX #PADDLE
|
||||
0x78, // SEI
|
||||
|
|
229
src/a2pid.c
229
src/a2pid.c
|
@ -58,7 +58,7 @@ struct {
|
|||
/*
|
||||
* Virtual drive info
|
||||
*/
|
||||
int vdrivefd[2];
|
||||
int vdrvfd[2];
|
||||
/*
|
||||
* ASCII to scancode conversion
|
||||
*/
|
||||
|
@ -353,100 +353,89 @@ static void sig_bye(int signo)
|
|||
}
|
||||
/*****************************************************************\
|
||||
* *
|
||||
* VDRIVE commands *
|
||||
* vdrv commands *
|
||||
* *
|
||||
\*****************************************************************/
|
||||
int vdriveopen(char *path)
|
||||
int vdrvopen(char *path)
|
||||
{
|
||||
char filename[256];
|
||||
strcpy(filename, path);
|
||||
strcat(filename, "A2VD1.PO");
|
||||
//printf("vdrive: open %s\n", filename);
|
||||
if ((vdrivefd[0] = open(filename, O_RDWR, 0)) < 0)
|
||||
vdrivefd[0] = 0;
|
||||
//printf("vdrv: open %s\n", filename);
|
||||
if ((vdrvfd[0] = open(filename, O_RDWR, 0)) < 0)
|
||||
vdrvfd[0] = 0;
|
||||
strcpy(filename, path);
|
||||
strcat(filename, "A2VD2.PO");
|
||||
//printf("vdrive: open %s\n", filename);
|
||||
if ((vdrivefd[1] = open(filename, O_RDWR, 0)) < 0)
|
||||
vdrivefd[1] = 0;
|
||||
return vdrivefd[0] + vdrivefd[1];
|
||||
//printf("vdrv: open %s\n", filename);
|
||||
if ((vdrvfd[1] = open(filename, O_RDWR, 0)) < 0)
|
||||
vdrvfd[1] = 0;
|
||||
return vdrvfd[0] + vdrvfd[1];
|
||||
}
|
||||
void vdriveclose(void)
|
||||
void vdrvclose(void)
|
||||
{
|
||||
if (vdrivefd[0]) close(vdrivefd[0]);
|
||||
if (vdrivefd[1]) close(vdrivefd[1]);
|
||||
vdrivefd[0] = vdrivefd[1] = 0;
|
||||
if (vdrvfd[0]) close(vdrvfd[0]);
|
||||
if (vdrvfd[1]) close(vdrvfd[1]);
|
||||
vdrvfd[0] = vdrvfd[1] = 0;
|
||||
}
|
||||
void vdrivecmd(int afd, int command, int block, unsigned char crc_in)
|
||||
unsigned char *prodos_time(void)
|
||||
{
|
||||
int i, vfd = vdrivefd[command >> 2];
|
||||
unsigned char block_buff[512], crc_out = 0xC5 ^ command ^ block ^ (block >> 8);
|
||||
static unsigned char time_buff[4];
|
||||
/*
|
||||
* Get ProDOS time.
|
||||
*/
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm = localtime(&now);
|
||||
int ptime = (tm->tm_mday & 0x1F)
|
||||
| (((tm->tm_mon + 1) & 0x0F) << 5)
|
||||
| (((tm->tm_year - 100) & 0x7F) << 9)
|
||||
| ((tm->tm_min & 0x3F) << 16)
|
||||
| ((tm->tm_hour & 0x1F) << 24);
|
||||
time_buff[0] = (unsigned char) ptime;
|
||||
time_buff[1] = (unsigned char) (ptime >> 8);
|
||||
time_buff[2] = (unsigned char) (ptime >> 16);
|
||||
time_buff[3] = (unsigned char) (ptime >> 24);
|
||||
return time_buff;
|
||||
}
|
||||
int vdrvtime(int afd)
|
||||
{
|
||||
return write(afd, prodos_time(), 4);
|
||||
}
|
||||
int vdrvstatus(int drive)
|
||||
{
|
||||
return vdrvfd[drive] == 0 ? 0x28 : 0x00;
|
||||
}
|
||||
int vdrvread(int afd, int drive, int block)
|
||||
{
|
||||
int err = 0, vfd = vdrvfd[drive];
|
||||
unsigned char block_buff[512];
|
||||
|
||||
if (crc_in != crc_out)
|
||||
prlog("vdrive: CRC mismatch!\n");
|
||||
if (command == 0x01 || command == 0x03 || command == 0x05)
|
||||
if (vfd)
|
||||
{
|
||||
//printf("vdrive: read block=%d from unit:%d\n", block, command >> 2);
|
||||
block_buff[0] = 0xC5;
|
||||
block_buff[1] = command;
|
||||
block_buff[2] = block;
|
||||
block_buff[3] = block >> 8;
|
||||
write(afd, block_buff, 4);
|
||||
if (command > 0x01)
|
||||
{
|
||||
unsigned char time_buff[4];
|
||||
/*
|
||||
* Get ProDOS time.
|
||||
*/
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm = localtime(&now);
|
||||
int ptime = (tm->tm_mday & 0x1F)
|
||||
| (((tm->tm_mon + 1) & 0x0F) << 5)
|
||||
| (((tm->tm_year - 100) & 0x7F) << 9)
|
||||
| ((tm->tm_min & 0x3F) << 16)
|
||||
| ((tm->tm_hour & 0x1F) << 24);
|
||||
time_buff[0] = (unsigned char) ptime;
|
||||
time_buff[1] = (unsigned char) (ptime >> 8);
|
||||
time_buff[2] = (unsigned char) (ptime >> 16);
|
||||
time_buff[3] = (unsigned char) (ptime >> 24);
|
||||
write(afd, time_buff, 4);
|
||||
crc_out ^= time_buff[0] ^ time_buff[1] ^ time_buff[2] ^ time_buff[3];
|
||||
}
|
||||
write(afd, &crc_out, 1);
|
||||
if (vfd)
|
||||
{
|
||||
lseek(vfd, block * 512, 0);
|
||||
read(vfd, block_buff, 512);
|
||||
}
|
||||
write(afd, block_buff, 512);
|
||||
for (crc_out = i = 0; i < 512; i++)
|
||||
crc_out ^= block_buff[i];
|
||||
write(afd, &crc_out, 1);
|
||||
}
|
||||
else if (command == 0x02 || command == 0x04)
|
||||
{
|
||||
//printf("vdrive: write block=%d to unit:%d\n", block, command >> 2);
|
||||
for (crc_out = i = 0; i < 512; i++)
|
||||
{
|
||||
read(afd, &block_buff[i], 1);
|
||||
crc_out ^= block_buff[i];
|
||||
}
|
||||
if (vfd)
|
||||
{
|
||||
lseek(vfd, block * 512, 0);
|
||||
read(afd, &crc_in, 1);
|
||||
}
|
||||
if (crc_in == crc_out)
|
||||
write(vfd, block_buff, 512);
|
||||
block_buff[0] = 0xC5;
|
||||
block_buff[1] = command;
|
||||
block_buff[2] = block;
|
||||
block_buff[3] = block >> 8;
|
||||
block_buff[4] = crc_out;
|
||||
write(afd, block_buff, 5);
|
||||
lseek(vfd, block * 512, 0);
|
||||
if (read(vfd, block_buff, 512) != 512)
|
||||
err = 0x27; /* ProDOS I/O error */
|
||||
}
|
||||
else
|
||||
state = RESET; // ??? What else to do ???
|
||||
err = 0x28; /* ProDOS No device connected error */
|
||||
write(afd, block_buff, 512);
|
||||
return err;
|
||||
}
|
||||
int vdrvwrite(int afd, int drive, int block)
|
||||
{
|
||||
int i, err = 0, vfd = vdrvfd[drive];
|
||||
unsigned char block_buff[512];
|
||||
|
||||
for (i = 0; i < 512; i++)
|
||||
read(afd, &block_buff[i], 1);
|
||||
if (vfd)
|
||||
{
|
||||
lseek(vfd, block * 512, 0);
|
||||
if (write(vfd, block_buff, 512) != 512)
|
||||
err = 0x27; /* ProDOS I/O error */
|
||||
}
|
||||
else
|
||||
err = 0x28; /* ProDOS No device connected error */
|
||||
return err;
|
||||
}
|
||||
/*****************************************************************\
|
||||
* *
|
||||
|
@ -722,12 +711,12 @@ void main(int argc, char **argv)
|
|||
struct uinput_user_dev uidev;
|
||||
struct termios oldtio,newtio;
|
||||
unsigned char iopkt[16];
|
||||
int i, c, rdycnt, vdriveactive;
|
||||
int i, c, rdycnt, vdrvactive;
|
||||
int a2fd, kbdfd, moufd, srvfd, maxfd;
|
||||
struct sockaddr_in servaddr;
|
||||
fd_set readset, openset;
|
||||
char *devtty = "/dev/ttyAMA0"; /* default for Raspberry Pi */
|
||||
char *vdrivedir = "/usr/share/a2pi/"; /* default VDRIVE image directory */
|
||||
char *vdrvdir = "/usr/share/a2pi/"; /* default vdrv image directory */
|
||||
|
||||
/*
|
||||
* Parse arguments
|
||||
|
@ -851,9 +840,16 @@ void main(int argc, char **argv)
|
|||
evrely.code = REL_Y;
|
||||
evsync.type = EV_SYN;
|
||||
/*
|
||||
* Get VDRIVE images.
|
||||
* Get vdrv images.
|
||||
*/
|
||||
vdriveactive = vdriveopen(vdrivedir);
|
||||
vdrvactive = vdrvopen(vdrvdir);
|
||||
#if defined(SETSERCLK) && defined(__ARMEL__)
|
||||
/*
|
||||
* Initialize ACIA clock for Apple II Pi card
|
||||
*/
|
||||
gpclk(271); /* divisor for ~1.8 MHz => (500/271) MHz */
|
||||
sleep(1); /* give clock chance to settle down */
|
||||
#endif
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
|
@ -869,13 +865,6 @@ void main(int argc, char **argv)
|
|||
die("error: bind socket");
|
||||
if (listen(srvfd, MAX_CLIENT - 1) < 0)
|
||||
die("error: listen socket");
|
||||
#if defined(SETSERCLK) && defined(__ARMEL__)
|
||||
/*
|
||||
* Initialize ACIA clock for Apple II Pi card
|
||||
*/
|
||||
gpclk(271); /* divisor for ~1.8 MHz => (500/271) MHz */
|
||||
sleep(1); /* give clock chance to settle down */
|
||||
#endif
|
||||
/*
|
||||
* Open serial port.
|
||||
*/
|
||||
|
@ -1092,22 +1081,48 @@ reset:
|
|||
else
|
||||
state = RESET;
|
||||
break;
|
||||
case 0xC5: /* virtual drive request */
|
||||
//printf("a2pid: vdrive request\n");
|
||||
case 0xA0: /* virtual drive 1 STATUS call */
|
||||
case 0xA2: /* virtual drive 2 STATUS call */
|
||||
//printf("vdrive: STATUS unit:%d\n", (iopkt[0] >> 1) & 0x01);
|
||||
iopkt[3] = iopkt[0] + 1; /* ack */
|
||||
write(a2fd, &iopkt[3], 1);
|
||||
iopkt[0] = vdrvstatus((iopkt[0] >> 1) & 0x01);
|
||||
write(a2fd, iopkt, 1);
|
||||
if (a2reqlist) /* resend last request */
|
||||
write(a2fd, &(a2reqlist->type), 1);
|
||||
break;
|
||||
case 0xA4: /* virtual drive 1 READ call */
|
||||
case 0xA6: /* virtual drive 2 READ call */
|
||||
//printf("vdrive: READ unit:%d block:%d\n", (iopkt[0] >> 1) & 0x01, iopkt[1] | (iopkt[2] << 8));
|
||||
iopkt[3] = iopkt[0] + 1; /* ack */
|
||||
write(a2fd, &iopkt[3], 1);
|
||||
iopkt[0] = vdrvread(a2fd, (iopkt[0] >> 1) & 0x01, iopkt[1] | (iopkt[2] << 8));
|
||||
write(a2fd, iopkt, 1);
|
||||
if (a2reqlist) /* resend last request */
|
||||
write(a2fd, &(a2reqlist->type), 1);
|
||||
break;
|
||||
case 0xA8: /* virtual drive 1 WRITE call */
|
||||
case 0xAA: /* virtual drive 2 WRITE call */
|
||||
//printf("vdrive: WRITE unit:%d block:%d\n", (iopkt[0] >> 1) & 0x01, iopkt[1] | (iopkt[2] << 8));
|
||||
iopkt[3] = iopkt[0] + 1; /* ack */
|
||||
write(a2fd, &iopkt[3], 1);
|
||||
newtio.c_cc[VMIN] = 1; /* blocking read until command packet received */
|
||||
tcsetattr(a2fd, TCSANOW, &newtio);
|
||||
if (read(a2fd, &iopkt[3], 1) + read(a2fd, &iopkt[4], 1) == 2)
|
||||
{
|
||||
//printf("vdrive cmd:%02X blk:%d crc:%02X\n", iopkt[1], iopkt[2] | (iopkt[3] << 8), iopkt[4]);
|
||||
vdrivecmd(a2fd, iopkt[1], iopkt[2] | (iopkt[3] << 8), iopkt[4]);
|
||||
}
|
||||
else
|
||||
state = RESET;
|
||||
iopkt[0] = vdrvwrite(a2fd, (iopkt[0] >> 1) & 0x01, iopkt[1] | (iopkt[2] << 8));
|
||||
write(a2fd, iopkt, 1);
|
||||
newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */
|
||||
tcsetattr(a2fd, TCSANOW, &newtio);
|
||||
if (a2reqlist) /* resend last request */
|
||||
write(a2fd, &a2reqlist->type, 1);
|
||||
write(a2fd, &(a2reqlist->type), 1);
|
||||
break;
|
||||
case 0xAC: /* virtual clock TIME call */
|
||||
//printf("vclock: TIME\n");
|
||||
iopkt[3] = 0xAD; /* ack */
|
||||
write(a2fd, &iopkt[3], 1);
|
||||
write(a2fd, prodos_time(), 4);
|
||||
if (a2reqlist) /* resend last request */
|
||||
write(a2fd, &(a2reqlist->type), 1);
|
||||
break;
|
||||
default:
|
||||
prlog("a2pid: Unknown Event\n");
|
||||
tcflush(a2fd, TCIFLUSH);
|
||||
|
@ -1217,15 +1232,15 @@ reset:
|
|||
case 0x98: /* get output chars from Apple II */
|
||||
a2client[i].flags |= CLIENT_COUT;
|
||||
break;
|
||||
case 0xC0: /* reconnect VDRIVEs */
|
||||
vdriveclose();
|
||||
vdriveactive = vdriveopen(vdrivedir);
|
||||
case 0xC0: /* reconnect vdrvs */
|
||||
vdrvclose();
|
||||
vdrvactive = vdrvopen(vdrvdir);
|
||||
iopkt[0]++; /* ack */
|
||||
write(a2client[i].fd, iopkt, 1);
|
||||
break;
|
||||
case 0xC2: /* disconnect VDRIVEs */
|
||||
vdriveclose();
|
||||
vdriveactive = 0;
|
||||
case 0xC2: /* disconnect vdrvs */
|
||||
vdrvclose();
|
||||
vdrvactive = 0;
|
||||
iopkt[0]++; /* ack */
|
||||
write(a2client[i].fd, iopkt, 1);
|
||||
break;
|
||||
|
@ -1259,7 +1274,7 @@ reset:
|
|||
close(a2client[i].fd);
|
||||
if (state == RESET)
|
||||
goto reset;
|
||||
vdriveclose();
|
||||
vdrvclose();
|
||||
shutdown(srvfd, SHUT_RDWR);
|
||||
close(srvfd);
|
||||
tcsetattr(a2fd, TCSANOW, &oldtio);
|
||||
|
|
Loading…
Reference in New Issue