Ading 4play

How to detect & use the 4play peripheral card
This commit is contained in:
Antoine Vignau 2022-10-29 21:20:41 +02:00
parent ba8b564bab
commit de8cad5750
11 changed files with 1859 additions and 0 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
4play/.DS_Store vendored Normal file

Binary file not shown.

BIN
4play/4play.2mg Normal file

Binary file not shown.

432
4play/DGR.DRIVER.S Normal file
View File

@ -0,0 +1,432 @@
*
* A simple DGR driver
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $1800
lst off
*---------- Some info
*
* The DGR page is similar to the 80-col screen
* Even columns on aux RAM, odd ones on main RAM
*
* There are two pixels per byte:
* - four high bits for the first pixel
* - four low bits for the second pixel
* - and so on...
* So, we have 80x48 pixels and 16 colors
*
* The routines are not optimized!
* There can be a second DGR page for
* flipping, use TXTPAGE1 or TXTPAGE2
* I did not code them here, sorry ;-)
*
*---------- Entry point
jmp DGROn ; Turn DGR on
jmp DGROff ; Turn DGR off
jmp DGRClear ; Clear screen
jmp DGRPutPixel ; Draw a pixel on screen
jmp DGRPutPixel2 ; Alt draw a pixel on screen
jmp DGRGetPixel ; Get the color of a pixel on screen
jmp DGRGetPixel2 ; Alt get the color of a pixel on screen
jmp DGRSetColor ; Set the pen color
jmp DGRSetXY ; Set X1/Y1 coordinates
jmp DGRSetXY2 ; Set X2/Y2 coordinates
jmp DGRSetPage ; Set page1/page2 data
jmp DGRDrawHLine ; Draw an horizontal line
jmp DGRDrawHLine2 ; Alt draw an horizontal line
jmp DGRDrawVLine ; Draw a vertical line
jmp DGRDrawVLine2 ; Alt draw a vertical line
*---------- Information
asc 8d
asc "DGR routines v1.0"8d
asc "(c) 2016, Brutal Deluxe"
asc 8d
*---------- Equates
maskHIGH = %11110000 ; Get high bits
maskLOW = %00001111 ; Get low bits
page1 = $04 ; High RAM ptr of DGR page 1 ($400..$7FF)
page2 = $08 ; same for page 2 ($800..$BFF)
dpSCREEN = $fe ; My usage of the zero page ;-)
minX = 0 ; 80px wide
maxX = 80
minY = 0 ; 48px height
maxY = 48
*--- Values
theCOLOR ds 1 ; color of
theCOLORHIGH ds 1 ; color for high bits (2 pixels per byte)
theCOLORFULL ds 1 ; 8-bit color (ORA of the two previous)
theX1 ds 1 ; where to draw a point
theY1 ds 1 ; again
theX2 ds 1 ; same for H and V lines
theY2 ds 1
thePAGE ds 1 ; may contain $04 (page 1) or $08 (page 2)
*--- Softswitches
KBD = $c000 ; the first softswitch
CLR80COL = $c000
SET80COL = $c001
RDMAINRAM = $c002
RDCARDRAM = $c003
WRMAINRAM = $c004
WRCARDRAM = $c005
SETSLOTCXROM = $c006
SETINTCXROM = $c007
SETSTDZP = $c008
SETALTZP = $c009
SETINTC3ROM = $c00a
SETSLOTC3ROM = $c00b
CLR80VID = $c00c
SET80VID = $c00d
TXTCLR = $c050
TXTSET = $c051
MIXCLR = $c052
MIXSET = $c053
TXTPAGE1 = $c054
TXTPAGE2 = $c055
LORES = $c056
HIRES = $c057
SETAN3 = $c05e
CLRAN3 = $c05f
*---------- Tables
ptrSCRl hex 0080008000800080
hex 28a828a828a828a8
hex 50d050d050d050d0
ptrSCRh hex 0000010102020303
hex 0000010102020303
hex 0000010102020303
*---------------------------
* DGROn
* Turn the DGR screen on
* Current video conf is not saved
*
DGROn = *
sta SET80COL ; enable 80 column store
sta SET80VID ; enable 80 column hardware
sta TXTCLR ; switch in graphics (not text)
sta MIXCLR ; clear mixed mode
sta LORES ; low-resolution graphics
sta SETAN3 ; clear annunciator 3
lda #page1 ; exit by forcing page 1
jmp DGRSetPage
*---------------------------
* DGROff
* Turn the DGR screen off
* Previous video conf is not restored
*
DGROff = *
sta CLRAN3 ; set annunciator 3
sta TXTPAGE1 ; switch in text page 1
sta MIXSET ; set mixed mode (4 lines text)
sta TXTSET ; switch in text (not graphics)
sta CLR80VID ; disable 80-column hardware
sta CLR80COL ; disable 80-column store
rts
*---------------------------
* DGRClear
* Clear the entire DGR screen
* with color A (ie. HOME)
*
* We assume we are on main RAM
* We erase in two passes
* to preserve the text holes
* - $0x00..$0x77
* - $0x80..$0xF7
*
DGRClear = *
jsr DGRSetColor ; set the colors
lda #0 ; point to the first page
sta dpSCREEN ; of the DGR screen
clear1 lda thePAGE ; on PAGE1 or PAGE2
sta dpSCREEN+1
lda theCOLORFULL ; get the full 8-bit color
ldx #4-1 ; number of pages to clear
clear2 ldy #127-8 ; we clear the main RAM page
]lp sta (dpSCREEN),y
dey
bpl ]lp
ldy #255-8 ; we clear the main RAM page
]lp sta (dpSCREEN),y
dey
bmi ]lp
sta WRCARDRAM ; we clear the aux RAM page
ldy #127-8
]lp sta (dpSCREEN),y
dey
bpl ]lp
ldy #255-8 ; we clear the aux RAM page
]lp sta (dpSCREEN),y
dey
bmi ]lp
sta WRMAINRAM ; go back to main RAM
inc dpSCREEN+1 ; next page
dex ; until the
bpl clear2 ; four are done
rts ; we're done
*---------------------------
* DGRPutPixel / DGRPutPixel2
* Draw a pixel on screen
* of color A and coords X,Y
*
DGRPutPixel = *
jsr DGRSetColor ; Save color
stx theX1 ; and coordinates
sty theY1
DGRPutPixel2 = *
lda theY1 ; Set the RAM pointer
lsr ; of the Y line
php ; save the carry!
tax
lda ptrSCRl,x
sta dpSCREEN
lda ptrSCRh,x
clc
adc thePAGE ; don't forget the page
sta dpSCREEN+1
*--- Put a pixel in main or aux RAM?
lda theX1 ; Now, determine where
lsr ; to put the pixel
tay
bcs putpixel1 ; odd means main RAM
sta WRCARDRAM ; we want aux RAM
putpixel1 plp ; we restore the carry to
bcs putpixel2 ; determine where to put the pixel
*--- Put in low bits
lda (dpSCREEN),y ; get the pixel
and #maskHIGH ; keep high bits
ora theCOLOR ; add the color
sta (dpSCREEN),y ; put the pixel
sta WRMAINRAM ; back in main RAM
rts
*--- Put in high bits
putpixel2 lda (dpSCREEN),y ; get the pixel
and #maskLOW ; keep low bits
ora theCOLORHIGH ; add the color
sta (dpSCREEN),y ; put the color
sta WRMAINRAM ; back in main RAM
rts
*---------------------------
* DGRGetPixel / DGRGetPixel2
* Get the color of a pixel
* at coords X,Y and return
* it in the Accumulator
*
DGRGetPixel = *
stx theX1
sty theY1
DGRGetPixel2 = *
lda theY1 ; Set the RAM pointer
lsr ; of the Y line
php ; save the carry!
tax
lda ptrSCRl,x
sta dpSCREEN
lda ptrSCRh,x
clc
adc thePAGE ; don't forget the page
sta dpSCREEN+1
*--- Get a pixel from main or aux RAM?
lda theX1 ; Now, determine where
lsr ; to put the pixel
tay
bcs getpixel1 ; odd means main RAM
sta RDCARDRAM ; we want aux RAM
getpixel1 plp ; we restore the carry to
bcs getpixel2 ; determine where to put the pixel
*--- Get in low bits
lda (dpSCREEN),y ; get the pixel
and #maskLOW ; keep high bits
sta RDMAINRAM ; back in main RAM
rts
*--- Get in high bits
getpixel2 lda (dpSCREEN),y ; get the pixel
and #maskHIGH ; keep high bits
lsr
lsr
lsr
lsr ; and return
sta RDMAINRAM ; back in main RAM
rts
*---------------------------
* DGRSetColor
* Define the pen color
* provided in the Accumulator
*
DGRSetColor = *
and #maskLOW ; keep low 4 bits
sta theCOLOR ; save color
asl ; calculate
asl ; color for
asl ; other pixel
asl ; in the same byte
sta theCOLORHIGH ; save it
ora theCOLOR ; add lower color
sta theCOLORFULL ; save the full one
rts
*---------------------------
* DGRSetXY
* Set X/Y coords for all actions
* through registers X and Y
*
DGRSetXY = *
stx theX1
sty theY1
rts
*---------------------------
* DGRSetXY2
* Set X2/Y2 coords for line drawing
* through registers X and Y
*
DGRSetXY2 = *
stx theX2
sty theY2
rts
*---------------------------
* DGRSetPage
* Set PAGE1 or PAGE2
* as the default DGR screen
* The routine does not force
* the page, it sets a value only
*
DGRSetPage = *
sta thePAGE
rts
*---------------------------
* DGRDrawHLine / DGRDrawHLine2
* Draw a line of color A
* from X1/Y1 to coords in registers X/Y
*
* Incorrect coordinates are NOT checked
*
DGRDrawHLine = *
jsr DGRSetColor
stx theX2
sty theY2
DGRDrawHLine2 = *
lda theY1 ; are Y the same?
cmp theY2
beq drawh1
sec ; error
rts
drawh1 lda theX2 ; X2>X1?
cmp theX1
bcs drawh2 ; OK
ldx theX1 ; exchange
stx theX2 ; the two
sta theX1 ; X coords
drawh2 jsr DGRPutPixel2 ; put a pixel
inc theX1 ; next X
lda theX1
cmp theX2 ; until the last
bcc drawh2
beq drawh2
rts
*---------------------------
* DGRDrawVLine / DGRDrawVLine2
* Draw a line of color A
* from X1/Y1 to coords in registers X/Y
*
* Incorrect coordinates are NOT checked
*
DGRDrawVLine = *
jsr DGRSetColor
stx theX2
sty theY2
DGRDrawVLine2 = *
lda theX1 ; are X the same?
cmp theX2
beq drawv1
sec ; error
rts
drawv1 lda theY2 ; Y2>Y1?
cmp theY1
bcs drawv2 ; OK
ldx theY1 ; exchange
stx theY2 ; the two
sta theY1 ; Y coords
drawv2 jsr DGRPutPixel2 ; put a pixel
inc theY1 ; next Y
lda theY1
cmp theY2 ; until the last
bcc drawv2
beq drawv2
rts
*--- End of code
ds \

449
4play/DGR.DRIVER2.S Normal file
View File

@ -0,0 +1,449 @@
*
* A simple DGR driver
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $1800
lst off
*---------- Some info
*
* The DGR page is similar to the 80-col screen
* Even columns on aux RAM, odd ones on main RAM
*
* There are two pixels per byte:
* - four high bits for the first pixel
* - four low bits for the second pixel
* - and so on...
* So, we have 80x48 pixels and 16 colors
*
* The routines are not optimized!
* There can be a second DGR page for
* flipping, use TXTPAGE1 or TXTPAGE2
* I did not code them here, sorry ;-)
*
*---------- Entry point
jmp DGROn ; Turn DGR on
jmp DGROff ; Turn DGR off
jmp DGRClear ; Clear screen
jmp DGRPutPixel ; Draw a pixel on screen
jmp DGRPutPixel2 ; Alt draw a pixel on screen
jmp DGRGetPixel ; Get the color of a pixel on screen
jmp DGRGetPixel2 ; Alt get the color of a pixel on screen
jmp DGRSetColor ; Set the pen color
jmp DGRSetXY ; Set X1/Y1 coordinates
jmp DGRSetXY2 ; Set X2/Y2 coordinates
jmp DGRSetPage ; Set page1/page2 data
jmp DGRDrawHLine ; Draw an horizontal line
jmp DGRDrawHLine2 ; Alt draw an horizontal line
jmp DGRDrawVLine ; Draw a vertical line
jmp DGRDrawVLine2 ; Alt draw a vertical line
*---------- Information
asc 8d
asc "DGR routines v1.0"8d
asc "(c) 2016, Brutal Deluxe"
asc 8d
*---------- Equates
maskHIGH = %11110000 ; Get high bits
maskLOW = %00001111 ; Get low bits
page1 = $04 ; High RAM ptr of DGR page 1 ($400..$7FF)
page2 = $08 ; same for page 2 ($800..$BFF)
dpSCREEN = $fe ; My usage of the zero page ;-)
minX = 0 ; 80px wide
maxX = 80
minY = 0 ; 48px height
maxY = 48
*--- Values
theCOLOR ds 1 ; color of
theCOLORHIGH ds 1 ; color for high bits (2 pixels per byte)
theCOLORFULL ds 1 ; 8-bit color (ORA of the two previous)
theX1 ds 1 ; where to draw a point
theY1 ds 1 ; again
theX2 ds 1 ; same for H and V lines
theY2 ds 1
thePAGE ds 1 ; may contain $04 (page 1) or $08 (page 2)
*--- Softswitches
KBD = $c000 ; the first softswitch
CLR80COL = $c000
SET80COL = $c001
RDMAINRAM = $c002
RDCARDRAM = $c003
WRMAINRAM = $c004
WRCARDRAM = $c005
SETSLOTCXROM = $c006
SETINTCXROM = $c007
SETSTDZP = $c008
SETALTZP = $c009
SETINTC3ROM = $c00a
SETSLOTC3ROM = $c00b
CLR80VID = $c00c
SET80VID = $c00d
TXTCLR = $c050
TXTSET = $c051
MIXCLR = $c052
MIXSET = $c053
TXTPAGE1 = $c054
TXTPAGE2 = $c055
LORES = $c056
HIRES = $c057
SETAN0 = $c058
CLRAN0 = $c059
SETAN1 = $c05a
CLRAN1 = $c05b
SETAN2 = $c05c
CLRAN2 = $c05d
SETAN3 = $c05e
CLRAN3 = $c05f
*---------- Tables
ptrSCRl hex 0080008000800080
hex 28a828a828a828a8
hex 50d050d050d050d0
ptrSCRh hex 0404050506060707
hex 0404050506060707
hex 0404050506060707
*---------------------------
* DGROn
* Turn the DGR screen on
* Current video conf is not saved
*
DGROn = *
sta TXTCLR ; switch in graphics (not text)
sta MIXCLR ; clear mixed mode
sta TXTPAGE1 ; page 1
sta LORES ; low-resolution graphics
ldx #2
]lp sta SET80COL ; enable 80 column store
sta CLRAN2 ; set annunciator 2
sta CLR80VID ; disable 80 column hardware
sta SETAN3 ; clear annunciator 3
sta CLRAN3 ; set annunciator 3
sta SET80VID ; enable 80 column hardware
sta SETAN3 ; clear annunciator 3
dex
bne ]lp
rts
*---------------------------
* DGROff
* Turn the DGR screen off
* Previous video conf is not restored
*
DGROff = *
sta CLRAN3 ; set annunciator 3
sta TXTPAGE1 ; switch in text page 1
sta MIXSET ; set mixed mode (4 lines text)
sta TXTSET ; switch in text (not graphics)
sta CLR80VID ; disable 80-column hardware
sta CLR80COL ; disable 80-column store
rts
*---------------------------
* DGRClear
* Clear the entire DGR screen
* with color A (ie. HOME)
*
* We assume we are on main RAM
* We erase in two passes
* to preserve the text holes
* - $0x00..$0x77
* - $0x80..$0xF7
*
DGRClear = *
jsr DGRSetColor ; set the colors
* lda #$00 ; point to the first page
* sta dpSCREEN ; of the DGR screen
*clear1 lda #$04 ; on PAGE1 or PAGE2
* sta dpSCREEN+1
lda #0
sta clearX+1
sta clearY+1
clear1 lda #4
sta clearX+2
sta clearY+2
lda theCOLORFULL ; get the full 8-bit color
ldx #4-1 ; number of pages to clear
clear2 ldy #127-8 ; we clear the main RAM page
clearX sta $bdbd,y
dey
bpl clearX
sta WRCARDRAM ; we clear the aux RAM page
ldy #127-8
clearY sta $bdbd,y
dey
bpl clearY
sta WRMAINRAM ; go back to main RAM
inc clearX+2 ; next page
inc clearY+2
dex ; until the
bpl clear2 ; four are done
lda clearX+1 ; check if we have done
bmi clear3 ; the second pass
lda #$80 ; no, so prepare it
sta clearX+1 ; and...
sta clearY+1
bne clear1 ; ...loop
clear3 rts ; we're done
*---------------------------
* DGRPutPixel / DGRPutPixel2
* Draw a pixel on screen
* of color A and coords X,Y
*
DGRPutPixel = *
jsr DGRSetColor ; Save color
stx theX1 ; and coordinates
sty theY1
DGRPutPixel2 = *
lda theY1 ; Set the RAM pointer
lsr ; of the Y line
php ; save the carry!
tax
lda ptrSCRl,x
sta dpSCREEN
lda ptrSCRh,x
* clc
* adc thePAGE ; don't forget the page
sta dpSCREEN+1
*--- Put a pixel in main or aux RAM?
lda theX1 ; Now, determine where
lsr ; to put the pixel
tay
bcs putpixel1 ; odd means main RAM
sta TXTPAGE2 ; we want aux RAM
putpixel1 plp ; we restore the carry to
bcc putpixel2 ; determine where to put the pixel
*--- Put in low bits
lda (dpSCREEN),y ; get the pixel
and #maskHIGH ; keep high bits
ora theCOLOR ; add the color
sta (dpSCREEN),y ; put the pixel
sta TXTPAGE1 ; back in main RAM
rts
*--- Put in high bits
putpixel2 lda (dpSCREEN),y ; get the pixel
and #maskLOW ; keep low bits
ora theCOLORHIGH ; add the color
sta (dpSCREEN),y ; put the color
sta TXTPAGE1 ; back in main RAM
rts
*---------------------------
* DGRGetPixel / DGRGetPixel2
* Get the color of a pixel
* at coords X,Y and return
* it in the Accumulator
*
DGRGetPixel = *
stx theX1
sty theY1
DGRGetPixel2 = *
lda theY1 ; Set the RAM pointer
lsr ; of the Y line
php ; save the carry!
tax
lda ptrSCRl,x
sta dpSCREEN
lda ptrSCRh,x
* clc
* adc thePAGE ; don't forget the page
sta dpSCREEN+1
*--- Get a pixel from main or aux RAM?
lda theX1 ; Now, determine where
lsr ; to put the pixel
tay
bcs getpixel1 ; odd means main RAM
sta TXTPAGE2 ; we want aux RAM
getpixel1 plp ; we restore the carry to
bcc getpixel2 ; determine where to put the pixel
*--- Get in low bits
lda (dpSCREEN),y ; get the pixel
and #maskLOW ; keep high bits
sta TXTPAGE1 ; back in main RAM
rts
*--- Get in high bits
getpixel2 lda (dpSCREEN),y ; get the pixel
and #maskHIGH ; keep high bits
lsr
lsr
lsr
lsr ; and return
sta TXTPAGE1 ; back in main RAM
rts
*---------------------------
* DGRSetColor
* Define the pen color
* provided in the Accumulator
*
DGRSetColor = *
and #maskLOW ; keep low 4 bits
sta theCOLOR ; save color
asl ; calculate
asl ; color for
asl ; other pixel
asl ; in the same byte
sta theCOLORHIGH ; save it
ora theCOLOR ; add lower color
sta theCOLORFULL ; save the full one
rts
*---------------------------
* DGRSetXY
* Set X/Y coords for all actions
* through registers X and Y
*
DGRSetXY = *
stx theX1
sty theY1
rts
*---------------------------
* DGRSetXY2
* Set X2/Y2 coords for line drawing
* through registers X and Y
*
DGRSetXY2 = *
stx theX2
sty theY2
rts
*---------------------------
* DGRSetPage
* Set PAGE1 or PAGE2
* as the default DGR screen
* The routine does not force
* the page, it sets a value only
*
DGRSetPage = *
sta thePAGE
rts
*---------------------------
* DGRDrawHLine / DGRDrawHLine2
* Draw a line of color A
* from X1/Y1 to coords in registers X/Y
*
* Incorrect coordinates are NOT checked
*
DGRDrawHLine = *
jsr DGRSetColor
stx theX2
sty theY2
DGRDrawHLine2 = *
lda theY1 ; are Y the same?
cmp theY2
beq drawh1
sec ; error
rts
drawh1 lda theX2 ; X2>X1?
cmp theX1
bcs drawh2 ; OK
ldx theX1 ; exchange
stx theX2 ; the two
sta theX1 ; X coords
drawh2 jsr DGRPutPixel2 ; put a pixel
inc theX1 ; next X
lda theX1
cmp theX2 ; until the last
bcc drawh2
beq drawh2
rts
*---------------------------
* DGRDrawVLine / DGRDrawVLine2
* Draw a line of color A
* from X1/Y1 to coords in registers X/Y
*
* Incorrect coordinates are NOT checked
*
DGRDrawVLine = *
jsr DGRSetColor
stx theX2
sty theY2
DGRDrawVLine2 = *
lda theX1 ; are X the same?
cmp theX2
beq drawv1
sec ; error
rts
drawv1 lda theY2 ; Y2>Y1?
cmp theY1
bcs drawv2 ; OK
ldx theY1 ; exchange
stx theY2 ; the two
sta theY1 ; Y coords
drawv2 jsr DGRPutPixel2 ; put a pixel
inc theY1 ; next Y
lda theY1
cmp theY2 ; until the last
bcc drawv2
beq drawv2
rts
*--- End of code
ds \

349
4play/FP.DRIVER.S Normal file
View File

@ -0,0 +1,349 @@
*
* Alex Lukazi's 4play routines
* http://lukazi.blogspot.com/
*
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $1000
lst off
*---------- Entry point
jmp FPInitAll ; Clear tables and variables
jmp FPFindAll ; Find all 4play cards
jmp FPFindIt ; Return 1st 4play card found (if any)
jmp FPLoopIt ; ...and you can continue looping
jmp FPReadDigital ; Read the joystick the new way
jmp FPSetAnalogClampValues ; Set the values for the old way
jmp FPReadAnalog ; Read the joystick the old way
jmp FPReadTrigger ; Read buttons
jmp FPReadTrigger1 ; Read buttons
jmp FPReadTrigger2 ; Read buttons
jmp FPReadTrigger3 ; Read buttons
jmp FPSetSlot ; Force 4play slot for...
jmp FPDirectRead ; ...a direct read of a joystick
*---------- Information
asc 8d
asc "6502 4play routines v1.0"8d
asc "(c) 2016, Brutal Deluxe Software"
asc 8d
*---------- Equates
*--- Mask bits
fpUP = %00000001 ; active high
fpDOWN = %00000010 ; active high
fpLEFT = %00000100 ; active high
fpRIGHT = %00001000 ; active high
fpNOTUSED = %00010000
fpTRIGGER3 = %00100000 ; active low
fpTRIGGER2 = %01000000 ; active high
fpTRIGGER1 = %10000000 ; active high
maskBIT0 = %11111110 ; #$FE masks bit 0
maskBIT1 = %11111101 ; #$FD masks bit 1
maskBIT2 = %11111011 ; #$FB masks bit 2
maskBIT3 = %11110111 ; #$F7 masks bit 3
maskBIT4 = %11101111 ; #$EF masks bit 4
maskBIT5 = %11011111 ; #$DF masks bit 5
maskBIT6 = %10111111 ; #$BF masks bit 6
maskBIT7 = %01111111 ; #$7F masks bit 7
*--- Values
fpDFTVALUE = $20 ; dft value for Rev. B
*--- Softswitches
KBD = $c000 ; the first softswitch
swSLOT0 = $80 ; as in $C080...
swSLOT7 = $F0 ; as in $C0F0...
swSLOT8 = $00 ; as in $C100... ahem...
*--- Zero page
dpF0 = $F0 ; For indirect access to a card
; $F2 for slot 1
; $FE for slot 7
*---------- Tables
curINDEX ds 1
fpTABLE ds 7 ; We can have up to 7 cards
fpTABLE2 ds 7 ; One entry per slot
*--- This table serves in digital to analog read
fpCLAMPTBL dfb $80 ; no movement
dfb $00 ; min up or left
dfb $ff ; max down or right
dfb $80 ; no movement
*---------------------------
* FPInitAll
* Do what is necessary
* to clear all data
*
FPInitAll = *
ldx #fpTABLE2-fpTABLE
lda #0
sta curINDEX ; reset index
]lp sta fpTABLE,x ; and the
sta fpTABLE2,x ; two tables
sta |dpF0,x ; beware on the IIgs
sta |dpF0+1,x ; beware on the IIgs
dex
bpl ]lp
rts
*---------------------------
* FPFindAll
* Find all the 4play cards
* in your Apple II computer
* by looking through the slots
*
* On exit:
* A: number of cards found
* Carry clear: we have 1+ card(s)
* set: no card found
*
FPFindAll = *
jsr FPFindIt ; try to find a 4play card
bcc FPLoopAll ; we have found one
lda curINDEX ; it is normally zero
rts ; no card found tell it
FPLoopAll ldy curINDEX ; when one found
sta fpTABLE,y ; save its slot
inc curINDEX
pha ; slot becomes index
asl ; 1=>2, 2=>4
tay ; the index
txa ; slot*16
sta |dpF0,y ; is stored in DP
lda #>KBD ; and the high value
sta |dpF0+1,y ; also
pla ; restore slot
tay ; slot becomes index
dey ; minus 1 (because table is 7b)
txa ; slot*16 in A
sta fpTABLE2,y ; save slot*16 in fpTABLE2,A
jsr FPLoopIt ; loop again (X is preserved)
bcc FPLoopAll ; another one found
lda curINDEX ; tell the number of cards found
clc ; tell we've found one at least
rts
*---------------------------
* FPFindIt
* Loop through the softswitches
* $C0s0..$C0s3 for 4 consecutive
* default value (see above)
*
* On exit:
* A: slot
* X: slot*16
* Carry clear: card found
* set: card not found
*
FPFindIt = *
ldx #swSLOT8
FPLoopIt = * ; Search for the default value
txa ; previous slot
sec
sbc #$10
tax
cpx #swSLOT0 ; until slot 0
bne FPLoopIt1 ; see if there is a card
sec ; no 4play card
rts
FPLoopIt1 lda KBD,x ; $C0s0
cmp #fpDFTVALUE
bne FPLoopIt
lda KBD+1,x ; $C0s1
cmp #fpDFTVALUE
bne FPLoopIt
lda KBD+2,x ; $C0s2
cmp #fpDFTVALUE
bne FPLoopIt
lda KBD+3,x ; $C0s3
cmp #fpDFTVALUE
bne FPLoopIt ; card not found
txa ; 4play card found
and #maskBIT7 ; mask bit 7 (= -#$80)
lsr
lsr
lsr
lsr ; X= slot*16
clc ; A= slot
rts ; done
*---------------------------
* FPSetSlot
*
* Set the slot of the 4play card
* to allow the FPDirectRead to
* read joystick values rapidly
*
* On entry:
* X: slot (1..7) of the 4play card
*
FPSetSlot = *
lda fpTABLE2-1,x ; coz slot 1 is offset 0
beq FPSetSlot1 ; no card, exit
sta FPDRPatch+1
clc ; with success
rts
FPSetSlot1 sec ; with error
rts
*---------------------------
* FPDirectRead
*
* This routine reads the
* indexed joystick data
*
* On entry:
* X: player's joystick (1..4)
*
FPDirectRead = *
dex ; from 1..4 to 0..3
FPDRPatch lda KBD,x ; $C090 for S1 .. $C0F0 for S7
inx ; from 0..3 to 1..4
rts
*---------------------------
* FPReadDigital
*
* On entry:
* X: joystick to read (1..4)
*
FPReadDigital = *
jmp FPDirectRead
*---------------------------
* FPSetAnalogClampValues
*
* This routine sets the clamp values
* used in the analog mode
*
* On entry:
* A: no movement value
* X: minimal value (up or left)
* Y: maximal value (down or right)
*
FPSetAnalogClampValues = *
sta fpCLAMPTBL
sta fpCLAMPTBL+3
stx fpCLAMPTBL+1
sty fpCLAMPTBL+2
rts
*---------------------------
* FPReadAnalog
*
* This routine returns analog values
* from a digital read. It is not similar
* to PREAD, the routine in ROM
*
* On entry:
* X: joystick to read (1..4)
*
* On exit:
* X: analog value for left/right
* Y: analog value for up/down
*
FPReadAnalog = *
jsr FPDirectRead
pha ; save joystick value
and #fpUP+fpDOWN ; keep up/down
tax ; get it in our table
lda fpCLAMPTBL,x
tay ; return in Y
pla ; restore joystick value
and #fpLEFT+fpRIGHT ; keep left/right
lsr ; /2
lsr ; /2
tax ; get it in our table
lda fpCLAMPTBL,x
tax ; return in X
rts
*---------------------------
* FPReadTrigger
*
* A set of routines to read the triggers
* (or buttons)
* Note that we read /TRIGGER3 (active low)
* whereas we read TRIGGER1 and TRIGGER2 (active high)
*
* The routines must be adapted according to your needs
*
* On entry:
* X: joystick to read (1..4)
*
FPReadTrigger = *
jsr FPDirectRead
and #fpTRIGGER1+fpTRIGGER2+fpTRIGGER3
clc ; <= if useless, remove
rts
FPReadTrigger1 = *
jsr FPDirectRead
and #fpTRIGGER1 ; because it is TRIGGER1
rts
FPReadTrigger2 = *
jsr FPDirectRead
and #fpTRIGGER2 ; because it is TRIGGER2
asl ; bit 6 > bit 7
rts
FPReadTrigger3 = *
jsr FPDirectRead
and #fpTRIGGER3
eor #fpTRIGGER3 ; because we read /TRIGGER3
asl ; bit 5 > bit 6
asl ; bit 6 > bit 7
rts
ds \

393
4play/GR.DRIVER.S Normal file
View File

@ -0,0 +1,393 @@
*
* A simple GR driver
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $1800
lst off
*---------- Some info
*
* The GR page is similar to the 40-col screen
*
* There are two pixels per byte:
* - four high bits for the first pixel
* - four low bits for the second pixel
* - and so on...
* So, we have 40x48 pixels and 16 colors
*
* The routines are not optimized!
*
*---------- Entry point
jmp GROn ; Turn GR on
jmp GROff ; Turn GR off
jmp GRClear ; Clear screen
jmp GRPutPixel ; Draw a pixel on screen
jmp GRPutPixel2 ; Alt draw a pixel on screen
jmp GRGetPixel ; Get the color of a pixel on screen
jmp GRGetPixel2 ; Alt get the color of a pixel on screen
jmp GRSetColor ; Set the pen color
jmp GRSetXY ; Set X1/Y1 coordinates
jmp GRSetXY2 ; Set X2/Y2 coordinates
jmp GRSetPage ; Set page1/page2 data
jmp GRDrawHLine ; Draw an horizontal line
jmp GRDrawHLine2 ; Alt draw an horizontal line
jmp GRDrawVLine ; Draw a vertical line
jmp GRDrawVLine2 ; Alt draw a vertical line
*---------- Information
asc 8d
asc "GR routines v1.0"8d
asc "(c) 2016, Brutal Deluxe"
asc 8d
*---------- Equates
maskHIGH = %11110000 ; Get high bits
maskLOW = %00001111 ; Get low bits
page1 = $04 ; High RAM ptr of GR page 1 ($400..$7FF)
page2 = $08 ; same for page 2 ($800..$BFF)
dpSCREEN = $fe ; My usage of the zero page ;-)
minX = 0 ; 80px wide
maxX = 40
minY = 0 ; 48px height
maxY = 48
*--- Values
theCOLOR ds 1 ; color of
theCOLORHIGH ds 1 ; color for high bits (2 pixels per byte)
theCOLORFULL ds 1 ; 8-bit color (ORA of the two previous)
theX1 ds 1 ; where to draw a point
theY1 ds 1 ; again
theX2 ds 1 ; same for H and V lines
theY2 ds 1
thePAGE ds 1 ; may contain $04 (page 1) or $08 (page 2)
*--- Softswitches
KBD = $c000 ; the first softswitch
CLR80COL = $c000
SET80COL = $c001
RDMAINRAM = $c002
RDCARDRAM = $c003
WRMAINRAM = $c004
WRCARDRAM = $c005
SETSLOTCXROM = $c006
SETINTCXROM = $c007
SETSTDZP = $c008
SETALTZP = $c009
SETINTC3ROM = $c00a
SETSLOTC3ROM = $c00b
CLR80VID = $c00c
SET80VID = $c00d
TXTCLR = $c050
TXTSET = $c051
MIXCLR = $c052
MIXSET = $c053
TXTPAGE1 = $c054
TXTPAGE2 = $c055
LORES = $c056
HIRES = $c057
SETAN3 = $c05e
CLRAN3 = $c05f
*---------- Tables
ptrSCRl hex 0080008000800080
hex 28a828a828a828a8
hex 50d050d050d050d0
ptrSCRh hex 0000010102020303
hex 0000010102020303
hex 0000010102020303
*---------------------------
* GROn
* Turn the GR screen on
* Current video conf is not saved
*
GROn = *
sta TXTCLR ; switch in graphics (not text)
sta MIXCLR ; clear mixed mode
sta TXTPAGE1 ; force page 1
sta LORES ; low-resolution graphics
lda #page1 ; exit by forcing page 1
jmp GRSetPage
*---------------------------
* GROff
* Turn the GR screen off
* Previous video conf is not restored
*
GROff = *
sta TXTPAGE1 ; switch in text page 1
sta MIXSET ; set mixed mode (4 lines text)
sta TXTSET ; switch in text (not graphics)
rts
*---------------------------
* GRClear
* Clear the entire GR screen
* with color A (ie. HOME)
*
* We preserve the text holes
* - $0x00..$0x77
* - $0x80..$0xF7
*
GRClear = *
jsr GRSetColor ; set the colors
lda #0 ; point to the first page
sta dpSCREEN ; of the GR screen
lda thePAGE ; on PAGE1 or PAGE2
sta dpSCREEN+1
lda theCOLORFULL ; get the full 8-bit color
ldx #4-1 ; number of pages to clear
clear2 ldy #127-8 ; we clear the RAM page
]lp sta (dpSCREEN),y
dey
bpl ]lp
ldy #255-8 ; we clear the RAM page
]lp sta (dpSCREEN),y
dey
bmi ]lp
inc dpSCREEN+1 ; next page
dex ; until the
bpl clear2 ; four are done
rts ; we're done
*---------------------------
* GRPutPixel / GRPutPixel2
* Draw a pixel on screen
* of color A and coords X,Y
*
GRPutPixel = *
jsr GRSetColor ; Save color
stx theX1 ; and coordinates
sty theY1
GRPutPixel2 = *
lda theY1 ; Set the RAM pointer
lsr ; of the Y line
php ; save the carry!
tax
lda ptrSCRl,x
sta dpSCREEN
lda ptrSCRh,x
clc
adc thePAGE ; don't forget the page
sta dpSCREEN+1
*--- Put a pixel
ldy theX1 ; Now, determine where to put the pixel
plp ; we restore the carry to
bcs putpixel2 ; determine where to put the pixel
*--- Put in low bits
lda (dpSCREEN),y ; get the pixel
and #maskHIGH ; keep high bits
ora theCOLOR ; add the color
sta (dpSCREEN),y ; put the pixel
rts
*--- Put in high bits
putpixel2 lda (dpSCREEN),y ; get the pixel
and #maskLOW ; keep low bits
ora theCOLORHIGH ; add the color
sta (dpSCREEN),y ; put the color
rts
*---------------------------
* GRGetPixel / GRGetPixel2
* Get the color of a pixel
* at coords X,Y and return
* it in the Accumulator
*
GRGetPixel = *
stx theX1
sty theY1
GRGetPixel2 = *
lda theY1 ; Set the RAM pointer
lsr ; of the Y line
php ; save the carry!
tax
lda ptrSCRl,x
sta dpSCREEN
lda ptrSCRh,x
clc
adc thePAGE ; don't forget the page
sta dpSCREEN+1
*--- Get a pixel
ldy theX1 ; Now, determine where to get the pixel
plp ; we restore the carry to
bcs getpixel2 ; determine where to get the pixel
*--- Get in low bits
lda (dpSCREEN),y ; get the pixel
and #maskLOW ; keep high bits
rts
*--- Get in high bits
getpixel2 lda (dpSCREEN),y ; get the pixel
and #maskHIGH ; keep high bits
lsr
lsr
lsr
lsr ; and return
rts
*---------------------------
* GRSetColor
* Define the pen color
* provided in the Accumulator
*
GRSetColor = *
and #maskLOW ; keep low 4 bits
sta theCOLOR ; save color
asl ; calculate
asl ; color for
asl ; other pixel
asl ; in the same byte
sta theCOLORHIGH ; save it
ora theCOLOR ; add lower color
sta theCOLORFULL ; save the full one
rts
*---------------------------
* GRSetXY
* Set X/Y coords for all actions
* through registers X and Y
*
GRSetXY = *
stx theX1
sty theY1
rts
*---------------------------
* GRSetXY2
* Set X2/Y2 coords for line drawing
* through registers X and Y
*
GRSetXY2 = *
stx theX2
sty theY2
rts
*---------------------------
* GRSetPage
* Set PAGE1 or PAGE2
* as the default GR screen
* The routine does not force
* the page, it sets a value only
*
GRSetPage = *
sta thePAGE
rts
*---------------------------
* GRDrawHLine / GRDrawHLine2
* Draw a line of color A
* from X1/Y1 to coords in registers X/Y
*
* Incorrect coordinates are NOT checked
*
GRDrawHLine = *
jsr GRSetColor
stx theX2
sty theY2
GRDrawHLine2 = *
lda theY1 ; are Y the same?
cmp theY2
beq drawh1
sec ; error
rts
drawh1 lda theX2 ; X2>X1?
cmp theX1
bcs drawh2 ; OK
ldx theX1 ; exchange
stx theX2 ; the two
sta theX1 ; X coords
drawh2 jsr GRPutPixel2 ; put a pixel
inc theX1 ; next X
lda theX1
cmp theX2 ; until the last
bcc drawh2
beq drawh2
rts
*---------------------------
* GRDrawVLine / GRDrawVLine2
* Draw a line of color A
* from X1/Y1 to coords in registers X/Y
*
* Incorrect coordinates are NOT checked
*
GRDrawVLine = *
jsr GRSetColor
stx theX2
sty theY2
GRDrawVLine2 = *
lda theX1 ; are X the same?
cmp theX2
beq drawv1
sec ; error
rts
drawv1 lda theY2 ; Y2>Y1?
cmp theY1
bcs drawv2 ; OK
ldx theY1 ; exchange
stx theY2 ; the two
sta theY1 ; Y coords
drawv2 jsr GRPutPixel2 ; put a pixel
inc theY1 ; next Y
lda theY1
cmp theY2 ; until the last
bcc drawv2
beq drawv2
rts
*--- End of code
ds \

1
4play/ReadMeFirst Normal file
View File

@ -0,0 +1 @@
4play source code (c) 2016, Brutal Deluxe Software ____________________________________________________________________ Hello and Happy new year 2017! This diskette contains some Apple IIgs source code that will help you understand how to handle the 4play joystick controller card. This demo was made in 2016 to test and support the 4play card by Alex Lucazi. Get yours at lukazi.blogspot.fr/2016/04/apple-ii-4play-joystick-card.html The card is supported by Ninjaforce's Kaboom. We also did a conversion of Broderbund's Lode Runner to support it. The diskette can be cold-booted or run from GS/OS. Antoine Vignau & Olivier Zardini Brutal Deluxe Software http://www.brutaldeluxe.fr/

82
4play/TEST.DGR.S Normal file
View File

@ -0,0 +1,82 @@
*
* DGR test program
*
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $300
lst off
*---------- Entry point
KBD = $C000
KBDSTROBE = $C010
*---------- Driver equates
DGROn = $1800 ; Turn DGR on
DGROff = DGROn+3 ; Turn DGR off
DGRClear = DGROff+3 ; Clear screen
DGRPutPixel = DGRClear+3 ; Draw a pixel on screen
DGRPutPixel2 = DGRPutPixel+3 ; Alt draw a pixel on screen
DGRGetPixel = DGRPutPixel2+3 ; Get the color of a pixel on screen
DGRGetPixel2 = DGRGetPixel+3 ; Alt get the color of a pixel on screen
DGRSetColor = DGRGetPixel2+3 ; Set the pen color
DGRSetXY = DGRSetColor+3 ; Set X1/Y1 coordinates
DGRSetXY2 = DGRSetXY+3 ; Set X2/Y2 coordinates
DGRSetPage = DGRSetXY2+3 ; Set page1/page2 data
DGRDrawHLine = DGRSetPage+3 ; Draw an horizontal line
DGRDrawHLine2 = DGRDrawHLine+3 ; Alt draw an horizontal line
DGRDrawVLine = DGRDrawHLine2+3 ; Draw a vertical line
DGRDrawVLine2 = DGRDrawVLine+3 ; Alt draw a vertical line
*---------- The code
jsr DGROn ; Turn DGR on
lda #$00 ; Set color to black
sta theCOLOR
clearLOOP lda theCOLOR ; Please erase the screen
jsr DGRClear
]lp lda KBD ; Wait for a keypress
bpl ]lp
bit KBDSTROBE
inc theCOLOR ; Next color, please
lda theCOLOR ; There are 16 of them
cmp #16
bne clearLOOP
*--- Test 2
ldx #0
ldy #0
jsr DGRSetXY
lda #6
ldx #79
ldy #0
jsr DGRDrawHLine
ldx #79
ldy #0
jsr DGRSetXY
lda #6
ldx #79
ldy #47
jsr DGRDrawVLine
jsr $fd0c
jsr DGROff ; Turn DGR off
rts ; Exit
*--- My test data
theCOLOR ds 1

71
4play/TEST.FP.S Normal file
View File

@ -0,0 +1,71 @@
*
* Alex Lukazi's 4play routines
* http://lukazi.blogspot.com/
*
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $300
lst off
*---------- Entry point
KBD = $C000
KBDSTROBE = $C010
PRBYTE = $FDDA
COUT = $FDED
*---------- Driver equates
FPInitAll = $1000 ; Clear tables and variables
FPFindAll = FPInitAll+3 ; Find all 4play cards
FPFindIt = FPFindAll+3 ; Return 1st 4play card found (if any)
FPLoopIt = FPFindIt+3 ; ...and you can continue looping
FPReadDigital = FPLoopIt+3 ; Read the joystick the new way
FPSetAnalogClampValues = FPReadDigital+3 ; Set the values for the old way
FPReadAnalog = FPSetAnalogClampValues+3 ; Read the joystick the old way
FPReadTrigger = FPReadAnalog+3 ; Read buttons
FPReadTrigger1 = FPReadTrigger+3 ; Read buttons
FPReadTrigger2 = FPReadTrigger1+3 ; Read buttons
FPReadTrigger3 = FPReadTrigger2+3 ; Read buttons
FPSetSlot = FPReadTrigger3+3 ; Force 4play slot for...
FPDirectRead = FPSetSlot+3 ; ...a direct read of a joystick
*---------- The code
jsr FPInitAll ; Clear all
jsr FPFindAll ; Find all 4play cards
lda $F9 ; Get slot high
jsr PRBYTE
lda $F8 ; Get slot low
jsr PRBYTE
ldx #$04 ; Force slot 4
jsr FPSetSlot
*---
]lp lda #$8D
jsr COUT
ldx #$01 ; Read first joystick
jsr FPDirectRead
jsr PRBYTE ; display its value
lda #$A0
jsr COUT
ldx #$02 ; Read second joystick
jsr FPDirectRead
jsr PRBYTE ; display its value
lda KBD ; loop until a
bpl ]lp ; key is pressed
bit KBDSTROBE ; exit
rts

82
4play/TEST.GR.S Normal file
View File

@ -0,0 +1,82 @@
*
* GR test program
*
* (c) 2016, Brutal Deluxe Software
* http://www.brutaldeluxe.fr/
*
* Use them at your own risk ;-)
*
mx %11
org $300
lst off
*---------- Entry point
KBD = $C000
KBDSTROBE = $C010
*---------- Driver equates
GROn = $1800 ; Turn DGR on
GROff = GROn+3 ; Turn DGR off
GRClear = GROff+3 ; Clear screen
GRPutPixel = GRClear+3 ; Draw a pixel on screen
GRPutPixel2 = GRPutPixel+3 ; Alt draw a pixel on screen
GRGetPixel = GRPutPixel2+3 ; Get the color of a pixel on screen
GRGetPixel2 = GRGetPixel+3 ; Alt get the color of a pixel on screen
GRSetColor = GRGetPixel2+3 ; Set the pen color
GRSetXY = GRSetColor+3 ; Set X1/Y1 coordinates
GRSetXY2 = GRSetXY+3 ; Set X2/Y2 coordinates
GRSetPage = GRSetXY2+3 ; Set page1/page2 data
GRDrawHLine = GRSetPage+3 ; Draw an horizontal line
GRDrawHLine2 = GRDrawHLine+3 ; Alt draw an horizontal line
GRDrawVLine = GRDrawHLine2+3 ; Draw a vertical line
GRDrawVLine2 = GRDrawVLine+3 ; Alt draw a vertical line
*---------- The code
jsr GROn ; Turn DGR on
lda #$00 ; Set color to black
sta theCOLOR
clearLOOP lda theCOLOR ; Please erase the screen
jsr GRClear
]lp lda KBD ; Wait for a keypress
bpl ]lp
bit KBDSTROBE
inc theCOLOR ; Next color, please
lda theCOLOR ; There are 16 of them
cmp #16
bne clearLOOP
*--- Test 2
ldx #0
ldy #0
jsr GRSetXY
lda #6
ldx #39
ldy #0
jsr GRDrawHLine
ldx #39
ldy #0
jsr GRSetXY
lda #6
ldx #39
ldy #47
jsr GRDrawVLine
jsr $fd0c
jsr GROff ; Turn DGR off
rts ; Exit
*--- My test data
theCOLOR ds 1