Added Atari 2600 library and documentation files vcs/include/*

This commit is contained in:
Curtis F Kaylor 2018-01-28 14:41:35 -05:00
parent 05d8d9fbb0
commit 50869e9c0f
37 changed files with 1524 additions and 34 deletions

148
vcs/include/arena.a02 Normal file
View File

@ -0,0 +1,148 @@
;arena.a02 - Two Line Arena Kernal for Atari 2600
;Requires Constants ARLINS, P0LINS and P1LINS
P0DRAW EQU $D0 ;Player 0 Draw Counter
P1DRAW EQU $D1 ;Player 1 Draw Counter
P0PTRL EQU $D2 ;Player 0 Graphics Pointer
P0PTRH EQU $D3
P1PTRL EQU $D4 ;Player 0 Graphics Pointer
P1PTRH EQU $D5
P0OFST: STA TEMP0 ;Save Multiplier
BEQ POFFSX ;If 0, Return
LDA #P0LINS ;Load # of Lines
BNE POFFST
P1OFST: STA TEMP0 ;Save Multiplier
BEQ POFFSX ;If 0, Return
LDA #P1LINS ;Load # of Lines
POFFST: STA TEMP1
POFFSL: TXA
CLC
ADC TEMP1
TAX
TYA
ADC #0
TAY
DEC TEMP0
BNE POFFSL
POFFSX: RTS
;p0prep() - Prepare Player 0 for Display
;Args: A - Y-Position
; X,Y - Address of Graphics Data
;Uses: ARLINS, P0LINS
;Sets: TEMP0 - Y-Position
;Affects; A,C,N,Z
P0PREP: LSR ;Divide by 2 for Two-line Position
STA TEMP0 ;Save Y Position
ROL ;Rotate Carry into Bit 1
EOR #1 ;Reverse It
STA VDELP0 ;and Store in Vertical Delay Register
LDA #ARLINS ;Draw = Top Line + Height - Y Position
CLC
ADC #P0LINS
SEC
SBC TEMP0
STA P0DRAW
TXA ;Pointer = GfxAddr + Height - 1 - Y Position
CLC
ADC #P0LINS-1
TAX
TYA
ADC #0
TAY
TXA
SEC
SBC TEMP0
STA P0PTRL
TYA
SBC #0
STA P0PTRH
RTS
;p1prep() - Prepare Player 1 for Display
;Args: A - Y-Position
; X,Y - Address of Graphics Data
;Uses: ARLINS, P1LINS
;Sets: TEMP1 - Y-Position
;Affects; A,C,N,Z
P1PREP: CLC ;Add 1 to Y-Position
ADC #1 ;to Compensate for GRP1 Priming
LSR ;Divide by 2 for Two-line Position
STA TEMP1 ;Save Y Position
ROL ;Rotate Carry into Bit 1
EOR #1 ;Reverse It
STA VDELP1 ;and Store in Vertical Delay Register
LDA #ARLINS ;Draw = Top Line + Height - Y Position + 1
CLC
ADC #P1LINS+1
SEC
SBC TEMP1
STA P1DRAW
TXA ;Pointer = GfxAddr + Height - 1 - Y Position
CLC
ADC #P1LINS-1
TAX
TYA
ADC #0
TAY
TXA
SEC
SBC TEMP1
STA P1PTRL
TYA
SBC #0
STA P1PTRH
RTS
;ardisp() - Kernel Display Routine
;Args: A = Playfield Color
;Uses: ARLINS, P0LINS, P1LINS, P0PTRL, P1PTRL
;Affects: A,X,Y,C,N,Z
ARDISP: STA COLUPF
LDY #ARLINS+1 ; 2 14 - Number of Kernal Lines (Scanlines / 2)
LDX #$FF ; - Initialize Playfield Index
LDA #1 ; - Reflect Playfield
STA CTRLPF ; - Set Playfield Control Register
LDA #P1LINS-1 ; - Preset GRP1 if Player 1 on Top Line
DCP P1DRAW ;
BCS ARDIS0 ;
LDA #0 ;
BYTE $2C ;
ARDIS0: LDA (P1PTRL),Y ;
STA GRP1 ; 3 6
DEY ; 2 ??
ARDISL: TYA ; 2 29 - Get Loop Counter
AND #ARMULT-1 ; 2 31 - Mask Against Multiplier
BNE ARDISS ; 2 33 If 0
INX ; 2 35 - Increment Playfield Pointer
ARDISS: LDA #P0LINS-1 ; 2 15 - Player 1 Height minus 1 due to STArting with 0
DCP P0DRAW ; 5 20 - Decrement P0DRAW and compare with height
BCS ARDIS1 ; 2 22 - If Player 0 not on Current Scanline
LDA #0 ; 2 24 - Load 0 (No Graphics)
BYTE $2C ; 4 28 - Else (BIT trick)
ARDIS1: LDA (P0PTRL),Y ;(5 28)- Load Player 0 Graphics Line
STA WSYNC ; 3 31 - Start Line 2
STA GRP0 ; 3 3 - Set Player 0 Graphics Data
LDA ARENA0,X ; 4 7 - get current scanline's playfield pattern
STA PF0 ; 3 10 - @0-22 and update it
LDA ARENA1,X ; 4 14 - get current scanline's playfield pattern
STA PF1 ; 3 17 - @71-28 and update it
LDA ARENA2,X ; 4 21 - get current scanline's playfield pattern
STA PF2 ; 3 24 - @60-39
LDA #P1LINS-1 ; 2 26 - Player 1 Height minus 1 due to STArting with 0
DCP P1DRAW ; 5 31 - Load 0 (No Graphics)
BCS ARDIS2 ; 2 33 - If Player 1 not on Current Scanline
LDA #0 ; 2 35 - Load 0 (No Graphics)
BYTE $2C ; 4 39 - Else (BIT trick)
ARDIS2: LDA (P1PTRL),Y ;(5 39)- Load Player 1 Graphics Line
STA WSYNC ; 3 42 - Start Line 2
STA GRP1 ; 3 3 - Set Player 1 Graphics Data
DEY ; 2 5 - Decrement Loop Counter
BNE ARDISL ; 2 7 - and Loop if >= 0
STY PF0 ; 3 10 - Clear Playfield
STY PF1 ; 3 13 -
STY PF2 ; 3 16 -
RTS

10
vcs/include/arena.h02 Normal file
View File

@ -0,0 +1,10 @@
/* Two Line Kernal Arena Kernal for Atari 2600 *
* Requires the following equates be set: *
* ARNLNS - Number of Scanlines to Display *
* P0HGHT - Height of Player 0 in Kernel Lines *
* P1HGHT - Height of Player 1 in Kernel Lines */
void p0prep(); //Prepare Player 0 for Display
void p1prep(); //Prepare Player 1 for Display
void ardisp(); //Display Arena

11
vcs/include/banks.a02 Normal file
View File

@ -0,0 +1,11 @@
;Bank Switching Registers
BANK0 EQU $1FF4 ;Select Bank 0 (32K)
BANK1 EQU $1FF5 ;Select Bank 1 (32K)
BANK2 EQU $1FF6 ;Select Bank 2 (32K) Bank 0 (16K) Switch Banks (8K)
BANK3 EQU $1FF7 ;Select Bank 3 (32K) Bank 1 (16K) Switch Banks (8K)
BANK4 EQU $1FF8 ;Select Bank 4 (32K) Bank 2 (16K)
BANK5 EQU $1FF9 ;Select Bank 5 (32K) Bank 3 (16K)
BANK6 EQU $1FFA ;Select Bank 6 (32K)
BANK7 EQU $1FFB ;Select Bank 7 (32K)

22
vcs/include/basinit.a02 Normal file
View File

@ -0,0 +1,22 @@
;Atari 2600 Initialization Code - C02 Assembly Language File
;Based on Batari Basic Initialization Code
START: SEI ;Disable Interrupts
CLD ;Disable Decimal Modes
LDY #0 ;Set Y-Index to $00
LDA $D0 ;If Location $D0
CMP #$2C ; Does Not Contain $2C
BNE IS2600 ;And
LDA $D1 ; Location $D1
CMP #$A9 ; Does Not Contain $D1
BNE IS2600 ;Then
DEY ; Set Y-Index to $FF
IS2600: LDX #0 ;
TXA ;
CLRMEM: INX ;Clear TIA Registers and RAM
TXS ; by Cycling Through All Stack Locations
PHA ; and Pushing 0
BNE CLRMEM ; which leaves Stack Pointer at $FF
TYA ;Copy 2600 Flag to Accumulator
JMP MAIN

45
vcs/include/colors.a02 Normal file
View File

@ -0,0 +1,45 @@
;colors.a02 - Atari 2600 Color/BW Assembly Language Routines
;getclr(mask, clr, bw) - Get Color Based on Color B&W Switch Position
;Args: A - Mask for Color Cycling (0=None)
; Y - Color/Luminance to use in Color Mode
; X - Color/Luminance to use in B&W Mode
;Returns: Color to Use
GETCLR: STA TEMP2 ;Save Color Cycling Mask
LDA SWCHB ;Read Console Switches
AND #%00001000 ;Test TV Type Switch
BNE GETCLC ;If Off
TXA ; Load B&W Mode Color/Luminance
EOR TEMP2 ; Apply Mask
AND #$0F ; and Strip High Nybble
RTS ;Else
GETCLC: TYA ; Load Color Mode Color/Luminance
EOR TEMP2 ; and Apply Apply Mask
RTS ;Return Selected Color
;setclr(mask, &clrtbl) - Set Object Colors
;Args: X,Y = Pointer to 8-Byte Color Table Color Table
; Player0, Player1, Playfield, Background (Color)
; Player0, Player1, Playfield, Background (B&W)
;Sets: TEMP0,TEMP1 = Pointer to Color Table
;Affects: A,X,Y,N,Z
SETCLR: STY TEMP1 ;Save Pointer to Color Table
STX TEMP0
STA TEMP2 ;Save Color Cycling Mask
LDX #3 ;Setting 4 colors (0-3)
LDY #3 ;Refault to the color entries in the table (0-3)
LDA SWCHB ;Read Console Switches
AND #%00001000 ;Test TV Type Switch
BNE SETCLL ;If On
LDA #$0F ; Use Color Entries
AND TEMP2 ;Else
STA TEMP2 ; Strip High Nybble from Mask
LDY #7 ; and Use B&W Entries
SETCLL: LDA (TEMP0),Y ;Get Color/B&W Value
EOR TEMP2 ;Apply Color Cycling Mask
STA COLUP0,x ;and Set Object Color
DEY ;Decrement Table Pointer
DEX ;Decrement Register Pointer
BPL SETCLL ;If >0, Loop
RTS ;Return

5
vcs/include/colors.h02 Normal file
View File

@ -0,0 +1,5 @@
/* Atari 2600 Library Functions for C02 */
void getclr(); //Select Color based on Color/B&W Switch
void setclr(); //Set Colors from Color Table

20
vcs/include/colors.txt Normal file
View File

@ -0,0 +1,20 @@
vcslib - Atari 2600 Library Functions for C02
This library contains commonly used functions for the Atari VCS.
setclr(&tbl); Sets all four system colors from array tbl,
based on the position of the Color/B&W
awitch.
The array consists of 8 bytes of TIA
Color/Luminance values, as follows:
Player 0 (Color Mode)
Player 1 (Color Mode)
Playfield (Color Mode)
Background (Color Mode)
Player 0 (B&W Mode)
Player 1 (B&W Mode)
Playfield (B&W Mode)
Background (B&W Mode)

101
vcs/include/digits.a02 Normal file
View File

@ -0,0 +1,101 @@
;===============================================================================
; Digit Graphics
;===============================================================================
align 256
DGTGFX: .byte %01110111
.byte %01010101
.byte %01010101
.byte %01010101
.byte %01110111
.byte %00010001
.byte %00010001
.byte %00010001
.byte %00010001
.byte %00010001
.byte %01110111
.byte %00010001
.byte %01110111
.byte %01000100
.byte %01110111
.byte %01110111
.byte %00010001
.byte %00110011
.byte %00010001
.byte %01110111
.byte %01010101
.byte %01010101
.byte %01110111
.byte %00010001
.byte %00010001
.byte %01110111
.byte %01000100
.byte %01110111
.byte %00010001
.byte %01110111
.byte %01110111
.byte %01000100
.byte %01110111
.byte %01010101
.byte %01110111
.byte %01110111
.byte %00010001
.byte %00010001
.byte %00010001
.byte %00010001
.byte %01110111
.byte %01010101
.byte %01110111
.byte %01010101
.byte %01110111
.byte %01110111
.byte %01010101
.byte %01110111
.byte %00010001
.byte %01110111
.byte %00100010
.byte %01010101
.byte %01110111
.byte %01010101
.byte %01010101
.byte %01100110
.byte %01010101
.byte %01100110
.byte %01010101
.byte %01100110
.byte %00110011
.byte %01000100
.byte %01000100
.byte %01000100
.byte %00110011
.byte %01100110
.byte %01010101
.byte %01010101
.byte %01010101
.byte %01100110
.byte %01110111
.byte %01000100
.byte %01100110
.byte %01000100
.byte %01110111
.byte %01110111
.byte %01000100
.byte %01100110
.byte %01000100
.byte %01000100

0
vcs/include/digits.h02 Normal file
View File

View File

@ -1,6 +1,12 @@
;k2line.a02 - Two Line Kernal Assembly Language File for C02
;Requires ConSTAnts KNLLNS, P0HGHT and P1HGHT
;Set Kernel Top Line
;;TODO - Adjust for Extra WSYNC in DSPLNS
;; Need to Execute a second WSYNC if KNLLNS is Even
KNLTOP EQU KNLLNS/2-1 ;Kernel Lines / 2 Scanlines - 1 (Zero Based)
P0DRAW EQU $D0 ;Player 0 Draw Counter
P1DRAW EQU $D1 ;Player 1 Draw Counter
P0PTRL EQU $D2 ;Player 0 Graphics Pointer
@ -19,7 +25,7 @@ P0PREP: LSR ;Divide by 2 for Two-line Position
ROL ;Rotate Carry into Bit 1
EOR #1 ;Reverse It
STA VDELP0 ;and Store in Vertical Delay Register
LDA #KNLLNS-1 ;Draw = Top Line + Height - Y Position
LDA #KNLTOP ;Draw = Top Line + Height - Y Position
CLC
ADC #P0HGHT
SEC
@ -54,7 +60,7 @@ P1PREP: CLC ;Add 1 to Y-Position
ROL ;Rotate Carry into Bit 1
EOR #1 ;Reverse It
STA VDELP1 ;and Store in Vertical Delay Register
LDA #KNLLNS-1 ;Draw = Top Line + Height - Y Position + 1
LDA #KNLTOP ;Draw = Top Line + Height - Y Position + 1
CLC
ADC #P1HGHT+1
SEC
@ -80,7 +86,7 @@ P1PREP: CLC ;Add 1 to Y-Position
;Args: None
;Uses: KNLLNS, P0HGHT, P1HGHT, P0PTRL, P1PTRL
;Affects: A,X,Y,C,N,Z
DSPLNS: LDY #KNLLNS ; - Number of Kernal Lines (Scanlines / 2)
DSPLNS: LDY #KNLTOP+1 ; - Number of Kernal Lines (Scanlines / 2)
LDA #1 ; - Reflect Playfield
STA CTRLPF ; - Set Playfield Control Register
LDA #P1HGHT-1 ; - Preset GRP1 if Player 1 on Top Line
@ -89,8 +95,6 @@ DSPLNS: LDY #KNLLNS ; - Number of Kernal Lines (Scanlines / 2)
LDA #0 ;
BYTE $2C ;
DSPLN0: LDA (P1PTRL),Y ;
STA WSYNC ; - Beginning of Line
STA HMOVE ; 3 3 - Position Objects
STA GRP1 ; 3 6
DEY ; 2 8
AND ($FF),Y ; 5 13 - Waste 5 Cycles to Match Line 2 Loop

112
vcs/include/k2line0.a02 Normal file
View File

@ -0,0 +1,112 @@
;k2line.a02 - Two Line Kernal Assembly Language File for C02
;Requires Constants PLYR0H and PLYR1H,
;Variables PLYR0D and PLYR1D, and Pointers PLYR0P and PLYR1P
PLYR0H EQU $D0 ;Player 0 Height
PLYR1H EQU $D1 ;Player 1 Height
PLYR0D EQU $D2 ;Player 0 Draw Counter
PLYR1D EQU $D3 ;Player 1 Draw Pointer
PLYR0P EQU $D4 ;Player 0 Graphics Pointer
PLYR1P EQU $D6 ;Player 1 Graphics Pointer
PLYR0T EQU $D8 ;Player 0 Pointer Offset
PLYR1T EQU $DA ;Player 1 Pointer Offset
SCNLNS EQU $DF ;Number of Scanlines
;setpl0() - Set Player 0 Data
;Args: A = Player 0 Height
; Y,X = Pointer to Player 0 Graphics Data
SETPL0: STA PLYR0H ;Save Player 0 Height
DEC PLYR0H ;and Decrement
STX PLYR0P ;Save Player 0 Pointer
STY PLYR0P+1
RTS
;setpl1() - Set Player 1 Data
;Args: A = Player 1 Height
; Y,X = Pointer to Player 1 Graphics Data
SETPL1: STA PLYR1H ;Save Player 1 Height
DEC PLYR1H ;and Decrement
STX PLYR1P ;Save Player 1 Pointer
STY PLYR1P+1
RTS
;prppl0() - Prep Player Variables
;Args: A = Player 0 Y-Position
PRPPL0: STA TEMP0
LDA SCNLNS ;PLYR0D = SCNLNS + PLYR0H - PLYR0Y
CLC
ADC PLYR0H
; ADC #1
SEC
SBC TEMP0
STA PLYR0D
LDA PLYR0P ;PLYR0T = PLYR0P + PLYR0H - PLYR0Y - 1
CLC
ADC PLYR0H
SEC
SBC TEMP0
STA PLYR0T
LDA PLYR0P+1
SBC #0
STA PLYR0T+1
RTS
;prppl1() - Prep Player 1 Variables
;Args: A = Player 1 Y Position
PRPPL1: STA TEMP1
LDA SCNLNS ;PLYR1D = SCNLNS + PLYR1H - PLYR1Y
CLC
ADC PLYR1H
; ADC #1
SEC
SBC TEMP1
STA PLYR1D
LDA PLYR1P ;PLYR1T = PLYR1P + PLYR1H - PLYR1Y - 1
CLC
ADC PLYR1H
SEC
SBC TEMP1
STA PLYR1T
LDA PLYR1P+1
SBC #0
STA PLYR1T+1
RTS
;prpdsp() - Prep Display
PRPDSP: LDA #0
STA WSYNC ;Wait for Horizontal Sync
STA HMOVE ;Move Objects
STA VDELP0 ;Clear Player 0 Vertical Delay
RTS
;dsplns() - Display Two Line Kernal
DSPLNS: LDY SCNLNS ; (13) Set Number of Lines to Draw
DEY
DSPLNL: LDA PLYR0H ;2 21 - Height of Player 0 (Zero Based)
DCP PLYR0D ;5 26 - Decrement PLYR0D and compare with height
BCS DSPLN0 ;2 28 - (3 23) If Player 0 not on Current Scanline
LDA #0 ;2 30 - Load Blank Line
BYTE $2C ;4 34 - Else (BIT trick)
DSPLN0: LDA (PLYR0T),Y ;5 49 - Load Player 0 Graphics Line
STA WSYNC ;3 52 - End of Line 2
STA GRP0 ;3 3 - Set Player 0 Graphics Data
LDX #%11111111 ;2 5 - Load Playfield Pattern
STX PF0 ;3 8 - and Store
STX PF1 ;3 11
STX PF2 ;3 14
LDA PLYR1H ;2 16 - Height of Player 1
DCP PLYR1D ;5 21 - Decrement PLYR1D and compare with height
BCS DSPLN1 ;2 23 - (3 18) If Player 0 not on Current Scanline
LDA #0 ;2 25 - Load Blank Line
BYTE $2C ;4 29 - - Else (BIT trick)
DSPLN1 LDA (PLYR1T),Y ;5 34 - Load Player 1 Graphics Line
STA WSYNC ;3 37 - End of Line 1
STA GRP1 ;3 3 - Set Player 0 Graphics Data
LDX #0 ;2 5 - Load Playfield Pattern
STX PF0 ;3 8 - and Store
STX PF1 ;3 11
STX PF2 ;3 14
DEY ;2 16 - decrease the 2LK loop counter
BPL DSPLNL ;2 18 - (3 21) Branch if more lines to draw
RTS

131
vcs/include/k2line1.a02 Normal file
View File

@ -0,0 +1,131 @@
;k2line.a02 - Two Line Kernal Assembly Language File for C02
;Requires Constants PLYR0H and PLYR1H,
;Variables PLYR0D and PLYR1D, and Pointers PLYR0P and PLYR1P
PLYR0H EQU $D0 ;Player 0 Height
PLYR1H EQU $D1 ;Player 1 Height
PLYR0D EQU $D2 ;Player 0 Draw Counter
PLYR1D EQU $D3 ;Player 1 Draw Pointer
PLYR0P EQU $D4 ;Player 0 Graphics Pointer
PLYR1P EQU $D6 ;Player 1 Graphics Pointer
PLYR0T EQU $D8 ;Player 0 Pointer Offset
PLYR1T EQU $DA ;Player 1 Pointer Offset
SCNLNS EQU $DF ;Number of Scanlines
;setpl0() - Set Player 0 Data
;Args: A = Player 0 Height
; Y,X = Pointer to Player 0 Graphics Data
SETPL0: STA PLYR0H ;Save Player 0 Height
DEC PLYR0H ;and Decrement
STX PLYR0P ;Save Player 0 Pointer
STY PLYR0P+1
RTS
;setpl1() - Set Player 1 Data
;Args: A = Player 1 Height
; Y,X = Pointer to Player 1 Graphics Data
SETPL1: STA PLYR1H ;Save Player 1 Height
DEC PLYR1H ;and Decrement
STX PLYR1P ;Save Player 1 Pointer
STY PLYR1P+1
RTS
;prppl0() - Prep Player Variables
;Args: A = Player 0 Y-Position
PRPPL0: LDX #1 ;Divide Y-Position by 2
SEC
SBC #1
LSR ;and Set Vertical Delay if No Remainder
STA TEMP0
BCS PRPPN0
STX VDELP0
PRPPN0: LDA SCNLNS ;PLYR0D = SCNLNS + PLYR0H - PLYR0Y
CLC
ADC PLYR0H
SEC
SBC TEMP0
STA PLYR0D
LDA PLYR0P ;PLYR0T = PLYR0P + PLYR0H - PLYR0Y - 1
CLC
ADC PLYR0H
SEC
SBC TEMP0
STA PLYR0T
LDA PLYR0P+1
SBC #0
STA PLYR0T+1
RTS
;prppl1() - Prep Player 1 Variables
;Args: A = Player 1 Y Position
PRPPL1: LDX #1
CLC ;Increment Y-Position
ADC #1 ; to compensate for priming of GRP1
LSR ;Divide by 2
STA TEMP1 ; and set Vertical Delay if No Remainder
BCS PRPPN1
STX VDELP1
PRPPN1: LDA SCNLNS ;PLYR1D = SCNLNS + PLYR1H - PLYR1Y
CLC
ADC #1
ADC PLYR1H
SEC
SBC TEMP1
STA PLYR1D
LDA PLYR1P ;PLYR1T = PLYR1P + PLYR1H - PLYR1Y - 1
CLC
ADC PLYR1H
SEC
SBC TEMP1
STA PLYR1T
LDA PLYR1P+1
SBC #
STA PLYR1T+1
RTS
;prpdsp() - Prep Display
PRPDSP: LDA #0
STA WSYNC ;Wait for Horizontal Sync
STA HMOVE ;Move Objects
STA VDELP0 ;Clear Player 0 Vertical Delay
STA VDELP1 ;Clear Player 0 Vertical Delay
RTS
;dsplns() - Display Two Line Kernal
DSPLNS: LDY SCNLNS ; (13) Set Number of Lines to Draw
LDA PLYR1H ; 2 9 - Get Player 1 Height
DCP PLYR1D ; 5 14 - Decrement counter and compare with height
BCS DSPLNP ; 2 16 - (3 18) If not on current scanline
LDA #0 ; 2 18 - Load Blank Line
BYTE $2C ; 4 22 - Else (BIT trick)
DSPLNP: LDA (PLYR1T),Y ; 5 22 - Load Player 0 Graphics Line
STA GRP1 ; 3 25 - Set Player 0 Graphics Data
DEY
DSPLNL: LDA PLYR0H ;2 21 - Height of Player 0 (Zero Based)
DCP PLYR0D ;5 26 - Decrement counter and compare with height
BCS DSPLN0 ;2 28 - (3 23) If Player 0 not on Current Scanline
LDA #0 ;2 30 - Load Blank Line
BYTE $2C ;4 34 - Else (BIT trick)
DSPLN0: LDA (PLYR0T),Y ;5 49 - Load Player 0 Graphics Line
STA WSYNC ;3 52 - End of Line 2
STA GRP0 ;3 3 - Set Player 0 Graphics Data
LDX #%11111111 ;2 5 - Load Playfield Pattern
STX PF0 ;3 8 - and Store
STX PF1 ;3 11
STX PF2 ;3 14
LDA PLYR1H ;2 16 - Get Player 1 Height
DCP PLYR1D ;5 21 - Decrement counter and compare with height
BCS DSPLN1 ;2 23 - (3 18) If not on current scanline
LDA #0 ;2 25 - Load Blank Line
BYTE $2C ;4 29 - - Else (BIT trick)
DSPLN1 LDA (PLYR1T),Y ;5 34 - Load Player 1 Graphics Line
STA WSYNC ;3 37 - End of Line 1
STA GRP1 ;3 3 - Set Player 0 Graphics Data
LDX #0 ;2 5 - Load Playfield Pattern
STX PF0 ;3 8 - and Store
STX PF1 ;3 11
STX PF2 ;3 14
DEY ;2 16 - decrease the 2LK loop counter
BPL DSPLNL ;2 18 - (3 21) Branch if more lines to draw
RTS

106
vcs/include/kernel.asm Normal file
View File

@ -0,0 +1,106 @@
processor 6502
include "vcs.h"
include "macro.h"
SEG
ORG $F000
Reset
StartOfFrame
; Start of vertical blank processing
lda #0
sta VBLANK
lda #2
sta VSYNC
; 3 scanlines of VSYNCH signal...
sta WSYNC
sta WSYNC
sta WSYNC
lda #0
sta VSYNC
; 37 scanlines of vertical blank...
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
; 192 scanlines of picture...
ldx #0
REPEAT 192; scanlines
inx
stx COLUBK
sta WSYNC
REPEND
lda #%01000010
sta VBLANK ; end of screen - enter blanking
; 30 scanlines of overscan...
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
jmp StartOfFrame
ORG $FFFA
.word Reset ; NMI
.word Reset ; RESET
.word Reset ; IRQ
END

5
vcs/include/notes.txt Normal file
View File

@ -0,0 +1,5 @@
Timer Setting
76/64 = 38/32 = 19/16
X*19 = X*16 + X*2 + X*1

6
vcs/include/scharge.a02 Normal file
View File

@ -0,0 +1,6 @@
;Atari VCS Supercharger Assembly Language Routines
SCCTL EQU $FFF8 ;Supercharger Control Register
SCAUD EQU $FFF9 ;Supercharger Audio Data

View File

@ -1,19 +1,18 @@
;Atari 2600 Two Player Score Kernel
;Score Routine Variables
SCORE0 EQU $E8 ;Player One Score
SCORE1 EQU $E9 ;Player Two Score
SC0ONE EQU $EA ;One Score Ones Digit Offset
SC1ONE EQU $EB ;Player Ten Score Ones Digit Offset
SC0TEN EQU $EC ;Player One Score Ones Digit Offset
SC1TEN EQU $ED ;Player Ten Score Ones Digit Offset
SC0GFX EQU $EE ;Player One Score Graphics Data
SC1GFX EQU $EF ;Player Two Score Graphics Data
SCORE0 EQU $E8 ;Player One Score
SCORE1 EQU $E9 ;Player Two Score
SC0ONE EQU $EA ;One Score Ones Digit Offset
SC1ONE EQU $EB ;Player Ten Score Ones Digit Offset
SC0TEN EQU $EC ;Player One Score Ones Digit Offset
SC1TEN EQU $ED ;Player Ten Score Ones Digit Offset
SC0GFX EQU $EE ;Player One Score Graphics Data
SC1GFX EQU $EF ;Player Two Score Graphics Data
;Prep Scores For Diplay
SCRPRP: LDX #1 ;Offset into SCORE0/SCORE1
SCRPRL: LDA SCORE0,X ;Get SCORE1 (First Pass) or SCORE0 (Second Pass)
SCPREP: LDX #1 ;Offset into SCORE0/SCORE1
SCPREL: LDA SCORE0,X ;Get SCORE1 (First Pass) or SCORE0 (Second Pass)
AND #$0F ;Remove Tens Digit
STA TEMP0 ;And Save It
ASL ;Multiply By 4
@ -30,14 +29,14 @@ SCRPRL: LDA SCORE0,X ;Get SCORE1 (First Pass) or SCORE0 (Second Pass)
ADC TEMP0 ;Add Saved Value, Resulting in Digit / 16 * 5
STA SC0TEN,X ;Store in SC0TEN (First Pass) or SC1TEN (Second Pass)
DEX ;Point to SCORE 1
BPL SCRPRL ;AND Loop if >0
BPL SCPREL ;AND Loop if >0
RTS ;Return
;Display Score Kernel - Uses 12 Lines Total
SCRDSP: LDA #2 ; - Use Player Colors
;scdisp() - Score Display Kernel - Uses 12 Scanlines Total
SCDISP: LDA #2 ; - Use Player Colors
STA CTRLPF ; - Set Playfield Control Register
LDX #5 ; 43 - cycle after looping
SCRDSL: LDY SC0TEN ; 3 46 - get the tens digit offset for the Score
SCDISL: LDY SC0TEN ; 3 46 - get the tens digit offset for the Score
LDA DGTGFX,Y ; 5 51 - use it to load the digit graphics
AND #$F0 ; 2 53 - remove the graphics for the ones digit
STA SC0GFX ; 3 56 - AND save it
@ -57,7 +56,7 @@ SCRDSL: LDY SC0TEN ; 3 46 - get the tens digit offset for the Score
AND #$0F ; 2 26 - remove the graphics for the tens digit
ORA SC1GFX ; 3 29 - merge with the tens digit graphics
STA SC1GFX ; 3 32 - AND save it
JSR SCRDSR ;12 44 - waste 12 cycles
JSR SCDISX ;12 44 - waste 12 cycles
STA PF1 ; 3 47 - @39-54, update playfield for Timer display
LDY SC0GFX ; 3 50 - preload for next scanline
STA WSYNC ; 3 53 - wait for end of scanline
@ -66,12 +65,12 @@ SCRDSL: LDY SC0TEN ; 3 46 - get the tens digit offset for the Score
INC SC1TEN ; 5 13 - advance for the next line of graphic data
INC SC0ONE ; 5 18 - advance for the next line of graphic data
INC SC1ONE ; 5 23 - advance for the next line of graphic data
JSR SCRDSR ;12 35 - waste 12 cycles
JSR SCDISX ;12 35 - waste 12 cycles
DEX ; 2 37 - decrease the loop counter
STA PF1 ; 3 40 - @39-54, update playfield for the Timer display
BNE SCRDSL ; 2 42 - (3 43) if dex != 0 then branch to ScoreLoop
BNE SCDISL ; 2 42 - (3 43) if dex != 0 then branch to ScoreLoop
STA WSYNC ; 3 45 - wait for end of scanline
STX PF1 ; 3 3 - x = 0, so this blanks out playfield
STA WSYNC ; 3 6 - wait for end of scanline
SCRDSR: RTS ; 6 12 - Return
SCDISX: RTS ; 6 12 - Return

View File

@ -1,13 +1,5 @@
/* Atari 2600 Two-Player Score Kernel */
char score1; //Player One Score
char score2; //Player Two Score
char sc1one; //Player One Score Ones Digit Offset
char sc1ten; //Player One Score Ones Digit Offset
char sc2one; //Player Ten Score Ones Digit Offset
char sc2ten; //Player Ten Score Ones Digit Offset
char sc1gfx; //Player One Score Graphics Data
char sc2gfx; //Player Two Score Graphics Data
char score0; //Player One Score
char score1; //Player Two Score

204
vcs/include/startup.a02 Normal file
View File

@ -0,0 +1,204 @@
;Atari 2600 Initialization Code - C02 Assembly Language File
PLR0X EQU $80
PLR1X EQU $81
MSL0X EQU $82
MSL1X EQU $83
BALLX EQU $84
OBJTY EQU $85
PLR0Y EQU $85
PLR1Y EQU $86
MSL1HT EQU $87
MSL1Y EQU $88
BALLY EQU $89
PLR0LO EQU $8A
PLR0HI EQU $8B
PLR1LO EQU $8C
PLR1HI EQU $8D
PLR0HT EQU $8E
PLR1HT EQU $8F
MSL0HT EQU $90
MSL0Y EQU $91
BALLHT EQU $92
SCORE EQU $93 ; $93-$95
SCOREPOINTERS EQU $96 ; $96-$9B EQU 6 BYTES
TEMP1 EQU $9C ;USED BY KERNEL
TEMP2 EQU $9D ;CAN BE USED IN PROGRAM TOO, BUT
TEMP3 EQU $9E ;ARE OBLITERATED WHEN DRAWSCREEN IS CALLED.
TEMP4 EQU $9F
TEMP5 EQU $A0
TEMP6 EQU $A1
RAND EQU $A2
SCORECOLOR EQU $A3
VAR0 EQU $A4
VAR1 EQU $A5
VAR2 EQU $A6
VAR3 EQU $A7
VAR4 EQU $A8
VAR5 EQU $A9
VAR6 EQU $AA
VAR7 EQU $AB
VAR8 EQU $AC
VAR9 EQU $AD
VAR10 EQU $AE
VAR11 EQU $AF
VAR12 EQU $B0
VAR13 EQU $B1
VAR14 EQU $B2
VAR15 EQU $B3
VAR16 EQU $B4
VAR17 EQU $B5
VAR18 EQU $B6
VAR19 EQU $B7
VAR20 EQU $B8
VAR21 EQU $B9
VAR22 EQU $BA
VAR23 EQU $BB
VAR24 EQU $BC
VAR25 EQU $BD
VAR26 EQU $BE
VAR27 EQU $BF
VAR28 EQU $C0
VAR29 EQU $C1
VAR30 EQU $C2
VAR31 EQU $C3
VAR32 EQU $C4
VAR33 EQU $C5
VAR34 EQU $C6
VAR35 EQU $C7
VAR36 EQU $C8
VAR37 EQU $C9
VAR38 EQU $CA
VAR39 EQU $CB
VAR40 EQU $CC
VAR41 EQU $CD
VAR42 EQU $CE
VAR43 EQU $CF
VAR44 EQU $D0
VAR45 EQU $D1
VAR46 EQU $D2
VAR47 EQU $D3
TEMP7 EQU $D4 ; THIS IS USED TO AID IN BANKSWITCHING
PLAYFIELDPOS EQU $D5
A EQU $D6
B EQU $D7
C EQU $D8
D EQU $D9
E EQU $DA
F EQU $DB
G EQU $DC
H EQU $DD
I EQU $DE
J EQU $DF
K EQU $E0
L EQU $E1
M EQU $E2
N EQU $E3
O EQU $E4
P EQU $E5
Q EQU $E6
R EQU $E7
S EQU $E8
T EQU $E9
U EQU $EA
V EQU $EB
W EQU $EC
X EQU $ED
Y EQU $EE
Z EQU $EF
; AVAILABLE FOR OTHER USES, OR IF UNUSED, PROVIDE MORE STACK SPACE
AUX1 EQU $F0
AUX2 EQU $F1
AUX3 EQU $F2
AUX4 EQU $F3
AUX5 EQU $F4
AUX6 EQU $F5
; PLAYFIELD COLOR/HT POINTERS
PFCOLORTABLE EQU $F0 ; AND $D5
PFHTTABLE EQU $F0 ; AND $D5
; THE ABOVE POINTERS ARE THE SAME BECAUSE IF COLOR AND HT ARE BOTH USED TOGETHER,
; THEY MUST USED ABSOLUTE INDEXED AND CANNOT USE POINTERS
LIFEPOINTER EQU $F2 ; POINTER TO "LIVES" SHAPE
; UPPER 3 BITS OF $F2 CONTAIN THE NUMBER OF LIVES
LIFECOLOR EQU $F4
LIVES EQU $F3 ; # LIVES >> 5
STATUSBARLENGTH EQU $F5 ; ONLY USES UPPER 5 BITS; OTHER BITS FREE
PFSCORE1 EQU $F2 ; OPTIONAL PLAYFIELD BYTES IN SCORE
PFSCORE2 EQU $F3
PFSCORECOLOR EQU $F4
STACK1 EQU $F6
STACK2 EQU $F7
STACK3 EQU $F8
STACK4 EQU $F9
START: SEI ;Disable Interrupts
CLD ;Disable Decimal Modes
LDY #0 ;Set Y-Index to $00
LDA $D0 ;If Location $D0
CMP #$2C ; Does Not Contain $2C
BNE IS2600 ;And
LDA $D1 ; Location $D1
CMP #$A9 ; Does Not Contain $D1
BNE IS2600 ;Then
DEY ; Set Y-Index to $FF
IS2600: LDX #0 ;Initialize X-Index
TXA ;Initialize Accumulator
CLRMEM: INX ;
TXS ;
PHA
BNE CLRMEM
STY TEMP1
IFCONST PFROWHT
LDA PFROWHT
ELSE
IFCONST PFRES
LDA #(96/PFRES)
ELSE
LDA #8
ENDIF
ENDIF
STA PLAYFIELDPOS
LDX #5
INITSCORE
LDA #<SCORETABLE
STA SCOREPOINTERS,X
DEX
BPL INITSCORE
LDA #1
STA CTRLPF
ORA INTIM
STA RAND
IFCONST MULTISPRITE
JSR MULTISPRITE_SETUP
ENDIF
IFNCONST BANKSWITCH
JMP GAME
ELSE
LDA #>(GAME-1)
PHA
LDA #<(GAME-1)
PHA
PHA
PHA
LDX #1
JMP BS_JSR
ENDIF

27
vcs/include/sticks.a02 Normal file
View File

@ -0,0 +1,27 @@
;C02 VCS Library - Joystick Assembly Language Subroutines
;getstk(cntrlr) - Read Joystick
;Args: A = Controller Number, 0=Left, 1=Right
;Sets: TEMP0 = Left Joystick Raw Directional Bits
; TEMP1 = Right Joystick Raw Directional Bits
; X = Controller Number
;Returns: A = Joystick Bits (1 if Pressed)
; 0=Up, 1=Down, 2=Left, 3=Right, 7=Trigger
; N = Set if Trigger Pressed
; Z = Set if No Buttons or Trigger Pressed
GETSTK: TAX ;Save Stick Number in Index
LDA SWCHA ;Read Joystick Register
LSR ;Shift High Nybble into Low Nybble
LSR
LSR
LSR
STA TEMP0 ;Save Left Joystick Raw Bits
LDA SWCHA ;Read Joystick Register
AND #$0F ;Strip High Nybble
STA TEMP1 ;Save Right Joystick Raw Bits
LDA INPT4,X ;Read Joystick Trigger
AND #$80 ;Strip Bits 1-6
ORA TEMP0,X ;Combine with Directional Bits
EOR #$8F ;Reverse Bits
RTS

10
vcs/include/sticks.h02 Normal file
View File

@ -0,0 +1,10 @@
/* Atari 2600 Joystick Functions for C02 */
//Joystick Directions
//#define STKUP = 1 //Joystick Up
//#define STKDN = 2 //Joystick Down
//#define STKLF = 4 //Joystick Left
//#define STKRT = 8 //Joystick Right
char getstk(); //Read Joystick

31
vcs/include/sticks.txt Normal file
View File

@ -0,0 +1,31 @@
sticks - Atari 2600 Joystick Functions for C02
This library contains a function for reading the joysticks:
res = getstk(cntrlr); Reads the state of the specified joystick.
The joystick to be read is specified by
the argument cntrlr:
0 = Left Joystick
1 = Right Joystick
Returns a byte comprised of the bits:
Bit Hex Dec Control
0 $01 1 Up
1 $02 2 Down
2 $03 4 Left
3 $04 8 Right
7 $05 128 Trigger
A 1 in a bit means that the direction
or trigger is pressed, so the function
will return 0 if they joystick is
centered and the trigger is not pressed.
This is the reverse of the raw bits from
the hardware ports.
Note: The raw bits for the left joystick
are stored in TEMP0, while the raw bits
for the right joystick are stored in TEMP1.

71
vcs/include/timerbar.a02 Normal file
View File

@ -0,0 +1,71 @@
;Atari 2600 Timer Bar Kernel
;Timer Variables
TMRPF0 EQU $F0 ;Timer Playfield Leftmost Byte
TMRPF1 EQU $F1
TMRPF2 EQU $F2
TMRPF3 EQU $F3
TMRPF4 EQU $F4
TMRPF5 EQU $F5 ;Timer Playfield Rightmost Byte
;tmprep() - Prepare Timer Bar
TMPREP: LDA #%11111111
STA TMRPF0
STA TMRPF1
STA TMRPF2
STA TMRPF3
STA TMRPF4
STA TMRPF5
RTS
;tmtick() - Tick Down Timer Bar
;Returns: A=$FF If Timer has Not Expired
; $00 If Timer has Expired
TMTICK: LDA TMRPF0 ;Check Leftmost Nybble of Timer Bar
AND #$F0 ;If 0
BEQ TMTICX ; Return FALSE
LSR TMRPF5 ;PF2 right side, reversed bits so shift right
ROL TMRPF4 ;PF1 right side, normal bits so shift left
ROR TMRPF3 ;PF0 right side, reversed bits so shift right
LDA TMRPF3 ;only upper nybble used, so we need to put bit 3 into C
LSR
LSR
LSR
LSR
ROR TMRPF2 ;PF2 left side, reversed bits so shift right
ROL TMRPF1 ;PF1 left side, normal bits so shift left
ROR TMRPF0 ;PF0 left side, reversed bits so shift right
LDA #$FF ;Return TRUE
TMTICX: RTS
;tmdisp() - Display Timer Bar
;Args: A = Timer Bar Color
TMDISP: STA COLUPF ; - Set Playfield Color
LDX #0 ; - Offset for Writes
STX CTRLPF ; - Set Playfield to Defaults
LDY #1 ; - Use Two Scanlines
TMDISL: STA WSYNC ; - Wait for Beginning of Line
LDA TMRPF0,X ; 4 4 - Copy Data to Playfield Left
STA PF0,X ; 5 9 - Indexed Mode Uses Extra Cycles
LDA TMRPF1,X ; 4 13
STA PF1,X ; 5 18
LDA TMRPF2,X ; 4 22
STA PF2,X ; 5 27
JSR TMDISX ;12 39 - Wait 12 Cycles
LDA TMRPF3 ; 3 42 - Copy Data To Playfield Right
STA PF0 ; 3 45
LDA TMRPF4 ; 3 50
STA PF1 ; 3 53
LDA TMRPF5 ; 3 56
STA PF2 ; 3 59
DEY ; 2 62
BPL TMDISL ; 2 64 (3 65)
STA WSYNC ; 3 67
LDA #0 ; 2 2
STA PF0 ; 3 5
STA PF1 ; 3 8
STA PF2 ; 3 11
STA COLUPF ; 3 14
STA WSYNC ; 3 20 - Gap between timer and Arena
TMDISX: RTS

3
vcs/include/timerbar.h02 Normal file
View File

@ -0,0 +1,3 @@
/* Atari 2600 Timer Bar Kernel */

55
vcs/include/vcsdefs.h02 Normal file
View File

@ -0,0 +1,55 @@
/* VCS Definitions Header */
//Boolean True and False
#define TRUE = $FF
#define FALSE = $0
//Set/Clear Various Registers
//ENAM0, ENAM1, ENABL - Enable/Disable Missiles, Ball
//REFP0, REFP01 - Enable/Disable Player Reflection
//RESPMO, RESPM1 - Disable/Enable Missiles
//VDELP0, VDELP1, VDELBL - Delay Players, Ball
#define CLEAR = 0
#define SET = $0B
//VBLANK Latches
#define TRGL = $40 //Enable Joystick Trigger Latch
#define DPDL = $80 //Dump Paddle Potentiometers
//NUSIZ0 and NUSIZ1 Missile Bit Masks
#define MS1CLK = 0 //1 Clock Wide Missile
#define MS2CLK = 1 //2 Clock Wide Missile
#define MS4CLK = 2 //4 Clock Wide Missile
#define MS8CLK = 3 //8 Clock Wide Missile
//NUSIZ0 and NUSIZ1 Player Bit Masks
#define PL1SNG = 0 //Single Sized Player
#define PL1DBL = 5 //Double Sized Player
#define PL1QUD = 7 //Quadruple Sized Player
#define PL2CLS = 1 //Two Close Copies of Player
#define PL2MED = 2 //Two Medium Copies of Player
#define PL2WID = 4 //Two Wide Copies of Player
#define PL3CLS = 3 //Three Close Copies of Player
#define PL3MED = 6 //Three Medium Copies of Player
//AUDC0 and AUDC1 Audio Control Registers
#define D02PUR = $04 //Divide by 2, Pure Tone
#define D06PUR = $0C //Divide by 6, Pure Tone
#define D32PUR = $06 //Divide by 31, Pure Tone
#define D93PUR = $0E //Divide by 93, Pure Tone
#define D00PL4 = $01 //No Divide, 4 Bit Polynomial
#define D00PL5 = $09 //No Divide, 5 Bit Polynomial
#define D00PL9 = $08 //No Divide, 9 Bit Polynomial
#define D15PL4 = $02 //Divide by 15 -> 4 Bit Polynomial
#define PL5PL4 = $03 //5 Bit Polynomial -> 4 Bit Polynomial
#define PL5D06 = $0F //5 Bit Polynomial -> Divide by 6
#define PL4502 = $07 //6 Bit Polynomial -> Divide by 2
//SWCHB Console Switch Bit Masks
#define P1DIFF = $80 //Player 1 Difficulty
#define P0DIFF = $40 //Player 0 Difficulty
#define CLRBW = $08 //Color/Black & White
#define SELECT = $02 //Game Select
#define RESET = $01 //Game Reset

9
vcs/include/vcsfoot.a02 Normal file
View File

@ -0,0 +1,9 @@
;vcsfoot.a02 - C02 Assembly Language Footer File for Atari 2600
;Created by Curtis F Kaylor - June 18, 2017
ORG $FFF4 ;Control and Interrupt Registers
DS 8 ;$FFF4-$FFF9 Bank Switch Registers
DC.W START ;$FFFC Reset Vector
DC.W IRQBRK ;$FFFE Interrupt Vector

9
vcs/include/vcsfoot.h02 Normal file
View File

@ -0,0 +1,9 @@
/* vcsfoot.h02 - C02 Footer File for Atari 2600 *
* The last line of the program must be *
* #include <vcsfoot.h> *
* The following two labels must be present in the program *
* irqbrk: subroutine to call when a BRK instruction is encountered *
* start: program start on power up */
#pragma vartable //Write Variable Table

79
vcs/include/vcshead.a02 Normal file
View File

@ -0,0 +1,79 @@
;vcshead.a02 - C02 Assembly Language Header file for Atari 2600
;based on VCS.H Version 1.05, 13/November/2003
;https://github.com/munsie/dasm/blob/master/machines/atari2600/vcs.h
;TIA Registers - Write
VSYNC EQU $00 ;0000 00x0 Vertical Sync Set-Clear
VBLANK EQU $01 ;xx00 00x0 Vertical Blank Set-Clear
WSYNC EQU $02 ;---- ---- Wait for Horizontal Blank
RSYNC EQU $03 ;---- ---- Reset Horizontal Sync Counter
NUSIZ0 EQU $04 ;00xx 0xxx Number-Size player/missle 0
NUSIZ1 EQU $05 ;00xx 0xxx Number-Size player/missle 1
COLUP0 EQU $06 ;xxxx xxx0 Color-Luminance Player 0
COLUP1 EQU $07 ;xxxx xxx0 Color-Luminance Player 1
COLUPF EQU $08 ;xxxx xxx0 Color-Luminance Playfield
COLUBK EQU $09 ;xxxx xxx0 Color-Luminance Background
CTRLPF EQU $0A ;00xx 0xxx Control Playfield, Ball, Collisions
REFP0 EQU $0B ;0000 x000 Reflection Player 0
REFP1 EQU $0C ;0000 x000 Reflection Player 1
PF0 EQU $0D ;xxxx 0000 Playfield Register Byte 0
PF1 EQU $0E ;xxxx xxxx Playfield Register Byte 1
PF2 EQU $0F ;xxxx xxxx Playfield Register Byte 2
RESP0 EQU $10 ;---- ---- Reset Player 0
RESP1 EQU $11 ;---- ---- Reset Player 1
RESM0 EQU $12 ;---- ---- Reset Missle 0
RESM1 EQU $13 ;---- ---- Reset Missle 1
RESBL EQU $14 ;---- ---- Reset Ball
AUDC0 EQU $15 ;0000 xxxx Audio Control 0
AUDC1 EQU $16 ;0000 xxxx Audio Control 1
AUDF0 EQU $17 ;000x xxxx Audio Frequency 0
AUDF1 EQU $18 ;000x xxxx Audio Frequency 1
AUDV0 EQU $19 ;0000 xxxx Audio Volume 0
AUDV1 EQU $1A ;0000 xxxx Audio Volume 1
GRP0 EQU $1B ;xxxx xxxx Graphics Register Player 0
GRP1 EQU $1C ;xxxx xxxx Graphics Register Player 1
ENAM0 EQU $1D ;0000 00x0 Graphics Enable Missle 0
ENAM1 EQU $1E ;0000 00x0 Graphics Enable Missle 1
ENABL EQU $1F ;0000 00x0 Graphics Enable Ball
HMP0 EQU $20 ;xxxx 0000 Horizontal Motion Player 0
HMP1 EQU $21 ;xxxx 0000 Horizontal Motion Player 1
HMM0 EQU $22 ;xxxx 0000 Horizontal Motion Missle 0
HMM1 EQU $23 ;xxxx 0000 Horizontal Motion Missle 1
HMBL EQU $24 ;xxxx 0000 Horizontal Motion Ball
VDELP0 EQU $25 ;0000 000x Vertical Delay Player 0
VDELP1 EQU $26 ;0000 000x Vertical Delay Player 1
VDELBL EQU $27 ;0000 000x Vertical Delay Ball
RESMP0 EQU $28 ;0000 00x0 Reset Missle 0 to Player 0
RESMP1 EQU $29 ;0000 00x0 Reset Missle 1 to Player 1
HMOVE EQU $2A ;---- ---- Apply Horizontal Motion
HMCLR EQU $2B ;---- ---- Clear Horizontal Move Registers
CXCLR EQU $2C ;---- ---- Clear Collision Latches
;TIA Regisers - Read bit 7 bit 6
CXM0P EQU $00 ;xx00 0000 Read Collision M0-P1 M0-P0
CXM1P EQU $01 ;xx00 0000 M1-P0 M1-P1
CXP0FB EQU $02 ;xx00 0000 P0-PF P0-BL
CXP1FB EQU $03 ;xx00 0000 P1-PF P1-BL
CXM0FB EQU $04 ;xx00 0000 M0-PF M0-BL
CXM1FB EQU $05 ;xx00 0000 M1-PF M1-BL
CXBLPF EQU $06 ;x000 0000 BL-PF
CXPPMM EQU $07 ;xx00 0000 P0-P1 M0-M1
INPT0 EQU $08 ;x000 0000 Read Pot Port 0
INPT1 EQU $09 ;x000 0000 Read Pot Port 1
INPT2 EQU $0A ;x000 0000 Read Pot Port 2
INPT3 EQU $0B ;x000 0000 Read Pot Port 3
INPT4 EQU $0C ;x000 0000 Read Input (Trigger) 0
INPT5 EQU $0D ;x000 0000 Read Input (Trigger) 1
; RIOT Registers
SWCHA EQU $280 ;Port A data register for joysticks:
;Bits 4-7 for player 1. Bits 0-3 for player 2.
SWACNT EQU $281 ;Port A data direction register (DDR)
SWCHB EQU $282 ;Port B data (console switches)
SWBCNT EQU $283 ;Port B DDR
INTIM EQU $284 ;Timer output
TIM1T EQU $294 ;set 1 clock interval
TIM8T EQU $295 ;set 8 clock interval
TIM64T EQU $296 ;set 64 clock interval
T1024T EQU $297 ;set 1024 clock interval

80
vcs/include/vcshead.h02 Normal file
View File

@ -0,0 +1,80 @@
//vcshead.h02 - C02 Header file for Atari 2600
//TIA Registers - Write
char VSYNC; //Vertical Sync
char VBLANK; //Vertical Blank
char WSYNC; //Wait for Horizontal Blank
char RSYNC; //Reset Horizontal Sync Counter
char NUSIZ0; //Number-Size Player/Missile 0
char NUSIZ1; //Number-Size Player/Missile 1
char COLUP0; //Color-Luminance Player 0
char COLUP1; //Color-Luminance Player 1
char COLUPF; //Color-Luminance Playfield
char COLUBK; //Color-Luminance Background
char CTRLPF; //Control Playfield, Ball, Collisions
char REFP0; //Reflection Player 0
char REFP1; //Reflection Player 1
char PF0; //Playfield Register Byte 0
char PF1; //Playfield Register Byte 1
char PF2; //Playfield Register Byte 2
char RESP0; //Reset Player 0
char RESP1; //Reset Player 1
char RESM0; //Reset Missle 0
char RESM1; //Reset Missle 1
char RESBL; //Reset Ball
char AUDC0; //Audio Control 0
char AUDC1; //Audio Control 1
char AUDF0; //Audio Frequency 0
char AUDF1; //Audio Frequency 1
char AUDV0; //Audio Volume 0
char AUDV1; //Audio Volume 1
char GRP0; //Graphics Register Player 0
char GRP1; //Graphics Register Player 1
char ENAM0; //0000 00x0 Graphics Enable Missle 0
char ENAM1; //0000 00x0 Graphics Enable Missle 1
char ENABL; //0000 00x0 Graphics Enable Ball
char HMP0; //Horizontal Motion Player 0
char HMP1; //Horizontal Motion Player 1
char HMM0; //Horizontal Motion Missle 0
char HMM1; //Horizontal Motion Missle 1
char HMBL; //Horizontal Motion Ball
char VDELP0; //0000 000x Vertical Delay Player 0
char VDELP1; //0000 000x Vertical Delay Player 1
char VDELBL; //0000 000x Vertical Delay Ball
char RESMP0; //0000 00x0 Reset Missle 0 to Player 0
char RESMP1; //0000 00x0 Reset Missle 1 to Player 1
char HMOVE; //Apply Horizontal Motion
char HMCLR; //Clear Horizontal Move Registers
char CXCLR; //Clear Collision Latches
//TIA Registers - Read bit 7 bit 6
char CXM0P; //Read Collision M0-P1 M0-P0
char CXM1P; // M1-P0 M1-P1
char CXP0FB; // P0-PF P0-BL
char CXP1FB; // P1-PF P1-BL
char CXM0FB; // M0-PF M0-BL
char CXM1FB; // M1-PF M1-BL
char CXBLPF; // BL-PF
char CXPPMM; // P0-P1 M0-M1
char INPT0; //Read Pot Port 0
char INPT1; //Read Pot Port 1
char INPT2; //Read Pot Port 2
char INPT3; //Read Pot Port 3
char INPT4; //Read Input (Trigger) 0
char INPT5; //Read Input (Trigger) 1
//RIOT Registers
char SWCHA; //Port A data register for joysticks:
//Bits 4-7 for Player 1. Bits 0-3 for Player 2.
char SWACNT; //Port A data direction register (DDR)
char SWCHB; //Port B data (console switches)
char SWBCNT; //Port B DDR
char INTIM; //Timer output
char TIM1T; //set 1 clock interval
char TIM8T; //set 8 clock interval
char TIM64T; //set 64 clock interval
char T1024T; //set 1024 clock interval
#pragma zeropage $80 //Zero Page RAM Base Address

19
vcs/include/vcsinit.a02 Normal file
View File

@ -0,0 +1,19 @@
;Atari 2600 Initialization Code - C02 Assembly Language File
; From CLEAN_START macro by Andrew Davie
; Standardised start-up code, clears stack, all TIA registers and RAM to 0
; Sets stack pointer to $FF, and all registers to 0
; Sets decimal mode off, sets interrupt flag (kind of un-necessary)
; Use as very first section of code on boot (ie: at reset)
; Code written to minimise total ROM usage - uses weird 6502 knowledge :)
START: SEI
CLD
LDX #0
TXA
TAY
STARTC: DEX
TXS
PHA
BNE STARTC
JMP MAIN

7
vcs/include/vcsinit.h02 Normal file
View File

@ -0,0 +1,7 @@
/* vcsinit.h02 - Initialize Atari 2600 *
* Usage: *
* #include <vcsfoot.h> *
* Contains the start label required by vcsfoot.h02 *
* Program must contain the following label *
* main: program code */

37
vcs/include/vcslib.a02 Normal file
View File

@ -0,0 +1,37 @@
;C02 VCS Library - Assembly Language Subroutines
;addbcd(addend, &varble) - Add Number to BCD variable
;adcbcd(addend, &varble) - Add Number w/Carry to BCD variable
;Args: A = Number to Add
; X,Y = Pointer to Variable to Add To
;Sets: TEMP0,TEMP1 = Pointer to Color Table
;Affects: A,Y,C,N,Z
;Updates: Variable Pointed to by X,Y
;Returns: A = Result of Addition
ADDBCD: CLC ;Clear Carry - Regular Add
ADCBCD: STX TEMP0 ;Save Pointer to Variable
STY TEMP1
LDY #0
SED ;Set Decimal Mode
ADC (TEMP0),Y ;Add Accumulator to Variable
STA (TEMP0),Y ;Store Result in Variable
CLD ;Clear Decimal Mode
RTS ;Return
;posobj(hrzpos, object) - Position Object
;Args: A = Horizontal Position
; Y = Object (0=Player0, 1=Player1, 2=Missile0, 3=Missle1, 4=Ball)
;Affects: A,C,Z
POSOBJ: SEC
STA WSYNC ;Wait for Beginning of Scanline
POSOBL: SBC #15 ;2 2 - each time thru this loop takes 5 cycles, which is
BCS POSOBL ;2 4 - the same amount of time it takes to draw 15 pixels
EOR #7 ;2 6 - The EOR & ASL statements convert the remainder
ASL ;2 8 - of position/15 to the value needed to fine tune
ASL ;2 10 - the X position
ASL ;2 12
ASL ;2 14
STA.WY HMP0,Y ;5 19 - store fine tuning of X
STA RESP0,Y ;4 23 - set coarse X position of object
RTS ;6 29

6
vcs/include/vcslib.h02 Normal file
View File

@ -0,0 +1,6 @@
/* Atari 2600 Library Functions for C02 */
char adcbcd(); //BCD Add w/Carry to Variable
char addbcd(); //BCD Add to Variable
void posobj(); //Position Object

34
vcs/include/vcslib.txt Normal file
View File

@ -0,0 +1,34 @@
vcslib - Atari 2600 Library Functions for C02
This library contains commonly used functions for the Atari VCS.
res = adcbcd(num, &var); Adds value num plus carry to variable var
using BCD arithmetic.
Used to update multi-byte BCD numbers, such
as scores with more than two digits.
Returns the updated contents of var. Can
be called as a void function if the result
is not needed.
res = addbcd(num, &var); Adds value num to variable var using BCD
arithmetic.
Used to update BCD numbers, such as two
digit scores.
Returns the updated contents of var. Can
be called as a void function if the result
is not needed.
posobj(hrz, obj); Sets horizontal position of object obj to
hrz.
Argument obj may be any of the following:
0 = Player 0
1 = Player 1
2 = Missile 0
3 = Missile 1
4 = Ball

3
vcs/include/vcsrtns.a02 Normal file
View File

@ -0,0 +1,3 @@
;vcsrtns.a02 - Atari 2600 Common Assembly Language Routines for C02

8
vcs/include/vcsrtns.h02 Normal file
View File

@ -0,0 +1,8 @@
/* vcsrtns.h02 - Common Atari 2600 Function for C02 *
* Usage: *
* #include <vcsrtns.h02> *
* Requires the following zero page variables: *
* TEMP0 *
* */

71
vcs/include/vcsstub.a02 Normal file
View File

@ -0,0 +1,71 @@
;Atart 2600 Program Stub - C02 Assembly Language File
;Preset Total Number of Kernal Lines
KNLLNS SET 192 ;192 Lines on NTSC Television
;Variables Used By Other Libraries
TEMP0 EQU $E0 ;Temporary Storage
TEMP1 EQU $E1
TEMP2 EQU $E2
TEMP3 EQU $E3
;Initialization Code
; From CLEAN_START macro by Andrew Davie
; Standardised STArt-up code, clears STAck, all TIA registers and RAM to 0
; Sets STAck pointer to $FF, and all registers to 0
; Sets decimal mode off, sets interrupt flag (kind of un-necessary)
; Use as very first section of code on boot (ie: at reset)
; Code written to minimise total ROM usage - uses weird 6502 knowledge :)
START: SEI
CLD
LDX #0
TXA
TAY
STARTC: DEX
TXS
PHA
BNE STARTC
JSR SETUP ;Execute Setup Code
MAIN: LDA #2 ;Vertical Sync On Bit Mask
LDX #49 ;41 scanlines * 76 cycles / 64
STA WSYNC ;Wait for SYNC (halts CPU until end of scanline)
STA VSYNC ;Turn On Vertical Sync
STX TIM64T ;Set timer to go off in 41 scanlines
STA WSYNC ;First Scanline of VSYNC
STA WSYNC ;Second Scanline of VSYNC
LDA #0 ;Vertical Sync Off Bit Mask
STA WSYNC ;Third Scanline of VSYNC
STA VSYNC ;Turn Off Vertical Sync
JSR VRTBLK ;Execute Vertical Blank Code
STA WSYNC ;Wait For Horizontal Sync
STA HMOVE ;Execute Horizontal Moves
JSR CLRHMX ;Clear Horizontal Move Registers
WTVBLK: STA WSYNC ;Wait for End of Vertical Blank
LDA INTIM ;Check Timer
BNE WTVBLK ;Loop If Not Zero
STA VBLANK ;Turn off Vertical Blank
JSR KERNEL ;Execute Kernel Code
STA WSYNC ;Wait for End of Scanline
LDA #2 ;Vertical Blank On Bit Mask
STA VBLANK ;Turn on Vertical Blank
LDA #32 ;27 scanlines * 76 cycles / 64
STA TIM64T ;Set Timer for 27 scanlines
JSR OVRSCN ;Execute Overscan Code
WTOSCN: STA WSYNC ;Wait for End of Overscan
LDA INTIM ;Check Time
BNE WTOSCN ;Loop If Not Zero
BEQ MAIN ;Loop Back to Vertical Sync
IRQBRK: RTI ;Catch 6502 Break Instructions
CLRHMR: NOP ; 2 8 (+6 for calling JSR)
JSR CLRHMX ;12 20
LDA #0 ; 2 22 - Clear Horizontal Move Registers
LDX #4 ; 2 24
CLRHML STA HMP0,X ; - Safe to Clear 24 Cycles after HMOVE
DEX
BPL CLRHML
CLRHMX: RTS

10
vcs/include/vcsstub.h02 Normal file
View File

@ -0,0 +1,10 @@
/* vcsstub.h02 - Atari 2600 Program Stub *
* Usage: *
* #include <vcsstub.h> *
* Contains the start label required by vcsfoot.h02 *
* Program must contain the following functions *
* setup() - Program Startup Code
* vrtblk() - Code to Execute During Vertical Blank *
* kernel() - Kernel Code - Draws Screen *
* ovrscn() - Code to Execute During Overscan */