From de8cad5750a8c227c36db2f1805789e67938a9c1 Mon Sep 17 00:00:00 2001 From: Antoine Vignau <34219772+antoinevignau@users.noreply.github.com> Date: Sat, 29 Oct 2022 21:20:41 +0200 Subject: [PATCH] Ading 4play How to detect & use the 4play peripheral card --- .DS_Store | Bin 8196 -> 10244 bytes 4play/.DS_Store | Bin 0 -> 6148 bytes 4play/4play.2mg | Bin 0 -> 819272 bytes 4play/DGR.DRIVER.S | 432 ++++++++++++++++++++++++++++++++++++++++++ 4play/DGR.DRIVER2.S | 449 ++++++++++++++++++++++++++++++++++++++++++++ 4play/FP.DRIVER.S | 349 ++++++++++++++++++++++++++++++++++ 4play/GR.DRIVER.S | 393 ++++++++++++++++++++++++++++++++++++++ 4play/ReadMeFirst | 1 + 4play/TEST.DGR.S | 82 ++++++++ 4play/TEST.FP.S | 71 +++++++ 4play/TEST.GR.S | 82 ++++++++ 11 files changed, 1859 insertions(+) create mode 100644 4play/.DS_Store create mode 100644 4play/4play.2mg create mode 100644 4play/DGR.DRIVER.S create mode 100644 4play/DGR.DRIVER2.S create mode 100644 4play/FP.DRIVER.S create mode 100644 4play/GR.DRIVER.S create mode 100644 4play/ReadMeFirst create mode 100644 4play/TEST.DGR.S create mode 100644 4play/TEST.FP.S create mode 100644 4play/TEST.GR.S diff --git a/.DS_Store b/.DS_Store index 4fa27c34a4dfb9a3e60f37cdb2d3d9cf66583de6..448de3a231e7ea3e77a0465c7b2b75f069b0b9f2 100644 GIT binary patch delta 264 zcmZp1XbF&DU|?W$DortDU{C-uIe-{M3-C-V6q~50C~ODhFar4u43#1#Tei3i8Cp!tczJ`DFq{m>^!$04V@^ R#{fi6E|BTn+$h4#3;;YXG$;T7 delta 118 zcmZn(XmOBWU|?W$DortDU;r^WfEYvza8E20o2aKKY6X%9@);P488R7?bJ7iilk+zR zN-SpI%+A5W!DzL)N8mTRATv-I5J+$X30IKzjfLNtC-bWWasV}h3}u)c&ogy%ttdM) E0G?44?f?J) diff --git a/4play/.DS_Store b/4play/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 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 + 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 \ + diff --git a/4play/DGR.DRIVER2.S b/4play/DGR.DRIVER2.S new file mode 100644 index 0000000..7088b79 --- /dev/null +++ b/4play/DGR.DRIVER2.S @@ -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 \ + diff --git a/4play/FP.DRIVER.S b/4play/FP.DRIVER.S new file mode 100644 index 0000000..a3f2d92 --- /dev/null +++ b/4play/FP.DRIVER.S @@ -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 \ + diff --git a/4play/GR.DRIVER.S b/4play/GR.DRIVER.S new file mode 100644 index 0000000..b5a8ead --- /dev/null +++ b/4play/GR.DRIVER.S @@ -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 \ + diff --git a/4play/ReadMeFirst b/4play/ReadMeFirst new file mode 100644 index 0000000..faec25c --- /dev/null +++ b/4play/ReadMeFirst @@ -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/ \ No newline at end of file diff --git a/4play/TEST.DGR.S b/4play/TEST.DGR.S new file mode 100644 index 0000000..2dd7e15 --- /dev/null +++ b/4play/TEST.DGR.S @@ -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 + diff --git a/4play/TEST.FP.S b/4play/TEST.FP.S new file mode 100644 index 0000000..b622953 --- /dev/null +++ b/4play/TEST.FP.S @@ -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 + diff --git a/4play/TEST.GR.S b/4play/TEST.GR.S new file mode 100644 index 0000000..d7a258e --- /dev/null +++ b/4play/TEST.GR.S @@ -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 +