1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-05-28 23:41:32 +00:00
8bitworkshop/src/worker/fs/fs2600basic.data
2018-11-20 12:31:19 -05:00

4215 lines
73 KiB
Plaintext

ifconst bankswitch
if bankswitch == 8
ORG $2FFC
RORG $FFFC
endif
if bankswitch == 16
ORG $4FFC
RORG $FFFC
endif
if bankswitch == 32
ORG $8FFC
RORG $FFFC
endif
else
ifconst ROM2k
ORG $F7FC
else
ORG $FFFC
endif
endif
.word start
.word start
; MACRO.H
; Version 1.05, 13/NOVEMBER/2003
VERSION_MACRO = 105
;
; THIS FILE IS EXPLICITLY SUPPORTED AS A DASM-PREFERRED COMPANION FILE
; PLEASE DO *NOT* REDISTRIBUTE MODIFIED VERSIONS OF THIS FILE!
;
; This file defines DASM macros useful for development for the Atari 2600.
; It is distributed as a companion machine-specific support package
; for the DASM compiler. Updates to this file, DASM, and associated tools are
; available at at http://www.atari2600.org/dasm
;
; Many thanks to the people who have contributed. If you take issue with the
; contents, or would like to add something, please write to me
; (atari2600@taswegian.com) with your contribution.
;
; Latest Revisions...
;
; 1.05 14/NOV/2003 - Added VERSION_MACRO equate (which will reflect 100x version #)
; This will allow conditional code to verify MACRO.H being
; used for code assembly.
; 1.04 13/NOV/2003 - SET_POINTER macro added (16-bit address load)
;
; 1.03 23/JUN/2003 - CLEAN_START macro added - clears TIA, RAM, registers
;
; 1.02 14/JUN/2003 - VERTICAL_SYNC macro added
; (standardised macro for vertical synch code)
; 1.01 22/MAR/2003 - SLEEP macro added.
; - NO_ILLEGAL_OPCODES switch implemented
; 1.0 22/MAR/2003 Initial release
; Note: These macros use illegal opcodes. To disable illegal opcode usage,
; define the symbol NO_ILLEGAL_OPCODES (-DNO_ILLEGAL_OPCODES=1 on command-line).
; If you do not allow illegal opcode usage, you must include this file
; *after* including VCS.H (as the non-illegal opcodes access hardware
; registers and require them to be defined first).
; Available macros...
; SLEEP n - sleep for n cycles
; VERTICAL_SYNC - correct 3 scanline vertical synch code
; CLEAN_START - set machine to known state on startup
; SET_POINTER - load a 16-bit absolute to a 16-bit variable
;-------------------------------------------------------------------------------
; SLEEP duration
; Original author: Thomas Jentzsch
; Inserts code which takes the specified number of cycles to execute. This is
; useful for code where precise timing is required.
; ILLEGAL-OPCODE VERSION DOES NOT AFFECT FLAGS OR REGISTERS.
; LEGAL OPCODE VERSION MAY AFFECT FLAGS
; Uses illegal opcode (DASM 2.20.01 onwards).
MAC SLEEP ;usage: SLEEP n (n>1)
.CYCLES SET {1}
IF .CYCLES < 2
ECHO "MACRO ERROR: 'SLEEP': Duration must be > 1"
ERR
ENDIF
IF .CYCLES & 1
IFNCONST NO_ILLEGAL_OPCODES
nop 0
ELSE
bit VSYNC
ENDIF
.CYCLES SET .CYCLES - 3
ENDIF
REPEAT .CYCLES / 2
nop
REPEND
ENDM
;-------------------------------------------------------------------------------
; VERTICAL_SYNC
; Original author: Manuel Polik
; Inserts the code required for a proper 3 scannline
; vertical sync sequence
;
; Note: Alters the accumulator
;
; IN:
; OUT: A = 1
MAC VERTICAL_SYNC
LDA #$02 ; A = VSYNC enable
STA WSYNC ; Finish current line
STA VSYNC ; Start vertical sync
STA WSYNC ; 1st line vertical sync
STA WSYNC ; 2nd line vertical sync
LSR ; A = VSYNC disable
STA WSYNC ; 3rd line vertical sync
STA VSYNC ; Stop vertical sync
ENDM
;-------------------------------------------------------------------------------
; CLEAN_START
; Original author: 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 :)
MAC CLEAN_START
sei
cld
ldx #0
txa
tay
.CLEAR_STACK dex
txs
pha
bne .CLEAR_STACK ; SP=$FF, X = A = Y = 0
ENDM
;-------------------------------------------------------
; SET_POINTER
; Original author: Manuel Rotschkar
;
; Sets a 2 byte RAM pointer to an absolute address.
;
; Usage: SET_POINTER pointer, address
; Example: SET_POINTER SpritePTR, SpriteData
;
; Note: Alters the accumulator, NZ flags
; IN 1: 2 byte RAM location reserved for pointer
; IN 2: absolute address
MAC SET_POINTER
.POINTER SET {1}
.ADDRESS SET {2}
LDA #<.ADDRESS ; Get Lowbyte of Address
STA .POINTER ; Store in pointer
LDA #>.ADDRESS ; Get Hibyte of Address
STA .POINTER+1 ; Store in pointer+1
ENDM
; EOF
; this file is screwed, I accidentally deleted the comments. Restore with version in .99b zip file.
2600basicheader.asm
bB.asm
std_kernel.asm
startup.asm
pf_drawing.asm
pf_scrolling.asm
std_routines.asm
std_overscan.asm
bB2.asm
score_graphics.asm
banksw.asm
2600basicfooter.asm
minikernel ; display up to 6 lives on screen
sta WSYNC
sleep 10 ; can we optimize this?
lda #0
ldy #7
sta VDELP0
sta VDELP1
ifnconst lives_compact
ifnconst lives_centered
sta RESP0
endif
lda.w lives
ifnconst lives_centered
sta RESP1
endif
lsr
lsr
lsr
lsr
ifconst lives_centered
sta RESP0
endif
lsr
tax
ifconst lives_centered
sta RESP1
endif
lda lifenusiz0table,x
sta NUSIZ0
lda lifenusiz1table,x
sta NUSIZ1
lda lifecolor
sta COLUP0
sta COLUP1
lda #$b0
sta HMP0
else
ifnconst lives_centered
sta.w RESP0
sta RESP1
endif
lda lives
lsr
lsr
lsr
lsr
lsr
tax
lda lifenusiz0table,x
ifconst lives_centered
sta RESP0
sta RESP1
sta.w NUSIZ0
else
sta NUSIZ0
endif
lda lifenusiz1table,x
sta NUSIZ1
lda lifecolor
sta COLUP0
sta COLUP1
lda #$10
sta HMP1
endif
sta HMOVE ; cycle 73
lifeloop
cpx #0
beq skipall
lda (lifepointer),y
sta GRP0
cpx #1
beq skipall
sta GRP1
skipall
dey
sta WSYNC
bpl lifeloop
iny
sty GRP0
sty GRP1
rts
if (<*) > $F5
align 256
endif
ifconst lives_compact
lifenusiz1table
.byte 0
lifenusiz0table
.byte 0,0,0,1,1,3,3,3
else
lifenusiz1table
.byte 0
lifenusiz0table
.byte 0,0,0,2,2,6,6,6
endif
; VCS.H
; Version 1.05, 13/November/2003
VERSION_VCS = 105
; THIS IS A PRELIMINARY RELEASE OF *THE* "STANDARD" VCS.H
; THIS FILE IS EXPLICITLY SUPPORTED AS A DASM-PREFERRED COMPANION FILE
; PLEASE DO *NOT* REDISTRIBUTE THIS FILE!
;
; This file defines hardware registers and memory mapping for the
; Atari 2600. It is distributed as a companion machine-specific support package
; for the DASM compiler. Updates to this file, DASM, and associated tools are
; available at at http://www.atari2600.org/dasm
;
; Many thanks to the original author(s) of this file, and to everyone who has
; contributed to understanding the Atari 2600. If you take issue with the
; contents, or naming of registers, please write to me (atari2600@taswegian.com)
; with your views. Please contribute, if you think you can improve this
; file!
;
; Latest Revisions...
; 1.05 13/NOV/2003 - Correction to 1.04 - now functions as requested by MR.
; - Added VERSION_VCS equate (which will reflect 100x version #)
; This will allow conditional code to verify VCS.H being
; used for code assembly.
; 1.04 12/NOV/2003 Added TIA_BASE_WRITE_ADDRESS and TIA_BASE_READ_ADDRESS for
; convenient disassembly/reassembly compatibility for hardware
; mirrored reading/writing differences. This is more a
; readability issue, and binary compatibility with disassembled
; and reassembled sources. Per Manuel Rotschkar's suggestion.
; 1.03 12/MAY/2003 Added SEG segment at end of file to fix old-code compatibility
; which was broken by the use of segments in this file, as
; reported by Manuel Polik on [stella] 11/MAY/2003
; 1.02 22/MAR/2003 Added TIMINT($285)
; 1.01 Constant offset added to allow use for 3F-style bankswitching
; - define TIA_BASE_ADDRESS as $40 for Tigervision carts, otherwise
; it is safe to leave it undefined, and the base address will
; be set to 0. Thanks to Eckhard Stolberg for the suggestion.
; Note, may use -DLABEL=EXPRESSION to define TIA_BASE_ADDRESS
; - register definitions are now generated through assignment
; in uninitialised segments. This allows a changeable base
; address architecture.
; 1.0 22/MAR/2003 Initial release
;-------------------------------------------------------------------------------
; TIA_BASE_ADDRESS
; The TIA_BASE_ADDRESS defines the base address of access to TIA registers.
; Normally 0, the base address should (externally, before including this file)
; be set to $40 when creating 3F-bankswitched (and other?) cartridges.
; The reason is that this bankswitching scheme treats any access to locations
; < $40 as a bankswitch.
IFNCONST TIA_BASE_ADDRESS
TIA_BASE_ADDRESS = 0
ENDIF
; Note: The address may be defined on the command-line using the -D switch, eg:
; dasm.exe code.asm -DTIA_BASE_ADDRESS=$40 -f3 -v5 -ocode.bin
; *OR* by declaring the label before including this file, eg:
; TIA_BASE_ADDRESS = $40
; include "vcs.h"
; Alternate read/write address capability - allows for some disassembly compatibility
; usage ; to allow reassembly to binary perfect copies). This is essentially catering
; for the mirrored ROM hardware registers.
; Usage: As per above, define the TIA_BASE_READ_ADDRESS and/or TIA_BASE_WRITE_ADDRESS
; using the -D command-line switch, as required. If the addresses are not defined,
; they defaut to the TIA_BASE_ADDRESS.
IFNCONST TIA_BASE_READ_ADDRESS
TIA_BASE_READ_ADDRESS = TIA_BASE_ADDRESS
ENDIF
IFNCONST TIA_BASE_WRITE_ADDRESS
TIA_BASE_WRITE_ADDRESS = TIA_BASE_ADDRESS
ENDIF
;-------------------------------------------------------------------------------
SEG.U TIA_REGISTERS_WRITE
ORG TIA_BASE_WRITE_ADDRESS
; DO NOT CHANGE THE RELATIVE ORDERING OF REGISTERS!
VSYNC ds 1 ; $00 0000 00x0 Vertical Sync Set-Clear
VBLANK ds 1 ; $01 xx00 00x0 Vertical Blank Set-Clear
WSYNC ds 1 ; $02 ---- ---- Wait for Horizontal Blank
RSYNC ds 1 ; $03 ---- ---- Reset Horizontal Sync Counter
NUSIZ0 ds 1 ; $04 00xx 0xxx Number-Size player/missle 0
NUSIZ1 ds 1 ; $05 00xx 0xxx Number-Size player/missle 1
COLUP0 ds 1 ; $06 xxxx xxx0 Color-Luminance Player 0
COLUP1 ds 1 ; $07 xxxx xxx0 Color-Luminance Player 1
COLUPF ds 1 ; $08 xxxx xxx0 Color-Luminance Playfield
COLUBK ds 1 ; $09 xxxx xxx0 Color-Luminance Background
CTRLPF ds 1 ; $0A 00xx 0xxx Control Playfield, Ball, Collisions
REFP0 ds 1 ; $0B 0000 x000 Reflection Player 0
REFP1 ds 1 ; $0C 0000 x000 Reflection Player 1
PF0 ds 1 ; $0D xxxx 0000 Playfield Register Byte 0
PF1 ds 1 ; $0E xxxx xxxx Playfield Register Byte 1
PF2 ds 1 ; $0F xxxx xxxx Playfield Register Byte 2
RESP0 ds 1 ; $10 ---- ---- Reset Player 0
RESP1 ds 1 ; $11 ---- ---- Reset Player 1
RESM0 ds 1 ; $12 ---- ---- Reset Missle 0
RESM1 ds 1 ; $13 ---- ---- Reset Missle 1
RESBL ds 1 ; $14 ---- ---- Reset Ball
AUDC0 ds 1 ; $15 0000 xxxx Audio Control 0
AUDC1 ds 1 ; $16 0000 xxxx Audio Control 1
AUDF0 ds 1 ; $17 000x xxxx Audio Frequency 0
AUDF1 ds 1 ; $18 000x xxxx Audio Frequency 1
AUDV0 ds 1 ; $19 0000 xxxx Audio Volume 0
AUDV1 ds 1 ; $1A 0000 xxxx Audio Volume 1
GRP0 ds 1 ; $1B xxxx xxxx Graphics Register Player 0
GRP1 ds 1 ; $1C xxxx xxxx Graphics Register Player 1
ENAM0 ds 1 ; $1D 0000 00x0 Graphics Enable Missle 0
ENAM1 ds 1 ; $1E 0000 00x0 Graphics Enable Missle 1
ENABL ds 1 ; $1F 0000 00x0 Graphics Enable Ball
HMP0 ds 1 ; $20 xxxx 0000 Horizontal Motion Player 0
HMP1 ds 1 ; $21 xxxx 0000 Horizontal Motion Player 1
HMM0 ds 1 ; $22 xxxx 0000 Horizontal Motion Missle 0
HMM1 ds 1 ; $23 xxxx 0000 Horizontal Motion Missle 1
HMBL ds 1 ; $24 xxxx 0000 Horizontal Motion Ball
VDELP0 ds 1 ; $25 0000 000x Vertical Delay Player 0
VDELP1 ds 1 ; $26 0000 000x Vertical Delay Player 1
VDELBL ds 1 ; $27 0000 000x Vertical Delay Ball
RESMP0 ds 1 ; $28 0000 00x0 Reset Missle 0 to Player 0
RESMP1 ds 1 ; $29 0000 00x0 Reset Missle 1 to Player 1
HMOVE ds 1 ; $2A ---- ---- Apply Horizontal Motion
HMCLR ds 1 ; $2B ---- ---- Clear Horizontal Move Registers
CXCLR ds 1 ; $2C ---- ---- Clear Collision Latches
;-------------------------------------------------------------------------------
SEG.U TIA_REGISTERS_READ
ORG TIA_BASE_READ_ADDRESS
; bit 7 bit 6
CXM0P ds 1 ; $00 xx00 0000 Read Collision M0-P1 M0-P0
CXM1P ds 1 ; $01 xx00 0000 M1-P0 M1-P1
CXP0FB ds 1 ; $02 xx00 0000 P0-PF P0-BL
CXP1FB ds 1 ; $03 xx00 0000 P1-PF P1-BL
CXM0FB ds 1 ; $04 xx00 0000 M0-PF M0-BL
CXM1FB ds 1 ; $05 xx00 0000 M1-PF M1-BL
CXBLPF ds 1 ; $06 x000 0000 BL-PF -----
CXPPMM ds 1 ; $07 xx00 0000 P0-P1 M0-M1
INPT0 ds 1 ; $08 x000 0000 Read Pot Port 0
INPT1 ds 1 ; $09 x000 0000 Read Pot Port 1
INPT2 ds 1 ; $0A x000 0000 Read Pot Port 2
INPT3 ds 1 ; $0B x000 0000 Read Pot Port 3
INPT4 ds 1 ; $0C x000 0000 Read Input (Trigger) 0
INPT5 ds 1 ; $0D x000 0000 Read Input (Trigger) 1
;-------------------------------------------------------------------------------
SEG.U RIOT
ORG $280
; RIOT MEMORY MAP
SWCHA ds 1 ; $280 Port A data register for joysticks:
; Bits 4-7 for player 1. Bits 0-3 for player 2.
SWACNT ds 1 ; $281 Port A data direction register (DDR)
SWCHB ds 1 ; $282 Port B data (console switches)
SWBCNT ds 1 ; $283 Port B DDR
INTIM ds 1 ; $284 Timer output
TIMINT ds 1 ; $285
; Unused/undefined registers ($285-$294)
ds 1 ; $286
ds 1 ; $287
ds 1 ; $288
ds 1 ; $289
ds 1 ; $28A
ds 1 ; $28B
ds 1 ; $28C
ds 1 ; $28D
ds 1 ; $28E
ds 1 ; $28F
ds 1 ; $290
ds 1 ; $291
ds 1 ; $292
ds 1 ; $293
TIM1T ds 1 ; $294 set 1 clock interval
TIM8T ds 1 ; $295 set 8 clock interval
TIM64T ds 1 ; $296 set 64 clock interval
T1024T ds 1 ; $297 set 1024 clock interval
;-------------------------------------------------------------------------------
; The following required for back-compatibility with code which does not use
; segments.
SEG
; EOF
; this file is screwed, I accidentally deleted the comments. Restore with version in .99b zip file.
superchipheader.asm
bB.asm
std_kernel.asm
startup.asm
pf_drawing.asm
pf_scrolling.asm
std_routines.asm
std_overscan.asm
bB2.asm
score_graphics.asm
banksw.asm
2600basicfooter.asm
; Compute mul1*mul2+acc -> acc:mul1 [mul2 is unchanged]
; Routine courtesy of John Payson (AtariAge member supercat)
; x and a contain multiplicands, result in a, temp1 contains any overflow
mul16
sty temp1
sta temp2
ldx #8
dec temp2
loopmul
lsr
ror temp1
bcc noaddmul
adc temp2
noaddmul
dex
bne loopmul
RETURN
; div int/int
; numerator in A, denom in temp1
; returns with quotient in A, remainder in temp1
div16
sty temp1
ldx #8
loopdiv
cmp temp1
bcc toosmalldiv
sbc temp1 ; Note: Carry is, and will remain, set.
rol temp2
rol
dex
bne loopdiv
beq donediv
toosmalldiv
rol temp2
rol
dex
bne loopdiv
donediv
sta temp1
lda temp2
RETURN
drawscreen
ifconst debugscore
ldx #14
lda INTIM ; display # cycles left in the score
ifconst mincycles
lda mincycles
cmp INTIM
lda mincycles
bcc nochange
lda INTIM
sta mincycles
nochange
endif
; cmp #$2B
; bcs no_cycles_left
bmi cycles_left
ldx #64
eor #$ff ;make negative
cycles_left
stx scorecolor
and #$7f ; clear sign bit
tax
lda scorebcd,x
sta score+2
lda scorebcd1,x
sta score+1
jmp done_debugscore
scorebcd
.byte $00, $64, $28, $92, $56, $20, $84, $48, $12, $76, $40
.byte $04, $68, $32, $96, $60, $24, $88, $52, $16, $80, $44
.byte $08, $72, $36, $00, $64, $28, $92, $56, $20, $84, $48
.byte $12, $76, $40, $04, $68, $32, $96, $60, $24, $88
scorebcd1
.byte 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6
.byte 7, 7, 8, 8, 9, $10, $10, $11, $12, $12, $13
.byte $14, $14, $15, $16, $16, $17, $17, $18, $19, $19, $20
.byte $21, $21, $22, $23, $23, $24, $24, $25, $26, $26
done_debugscore
endif
ifconst debugcycles
lda INTIM ; if we go over, it mucks up the background color
; cmp #$2B
; BCC overscan
bmi overscan
sta COLUBK
bcs doneoverscan
endif
overscan
lda INTIM ;wait for sync
bmi overscan
doneoverscan
;do VSYNC
lda #2
sta WSYNC
sta VSYNC
STA WSYNC
STA WSYNC
LDA #0
STA WSYNC
STA VSYNC
sta VBLANK
ifnconst overscan_time
lda #37+128
else
lda #overscan_time+128
endif
sta TIM64T
ifconst legacy
if legacy < 100
ldx #4
adjustloop
lda player0x,x
sec
sbc #14 ;?
sta player0x,x
dex
bpl adjustloop
endif
endif
if (<*)>$F0
align 256, $EA
endif
sta WSYNC
ldx #4
SLEEP 3
HorPosLoop ; 5
lda player0x,X ;+4 9
sec ;+2 11
DivideLoop
sbc #15
bcs DivideLoop;+4 15
sta temp1,X ;+4 19
sta RESP0,X ;+4 23
sta WSYNC
dex
bpl HorPosLoop;+5 5
; 4
ldx #4
ldy temp1,X
lda repostable-256,Y
sta HMP0,X ;+14 18
dex
ldy temp1,X
lda repostable-256,Y
sta HMP0,X ;+14 32
dex
ldy temp1,X
lda repostable-256,Y
sta HMP0,X ;+14 46
dex
ldy temp1,X
lda repostable-256,Y
sta HMP0,X ;+14 60
dex
ldy temp1,X
lda repostable-256,Y
sta HMP0,X ;+14 74
sta WSYNC
sta HMOVE ;+3 3
ifconst legacy
if legacy < 100
ldx #4
adjustloop2
lda player0x,x
clc
adc #14 ;?
sta player0x,x
dex
bpl adjustloop2
endif
endif
;set score pointers
lax score+2
jsr scorepointerset
sty scorepointers+5
stx scorepointers+2
lax score+1
jsr scorepointerset
sty scorepointers+4
stx scorepointers+1
lax score
jsr scorepointerset
sty scorepointers+3
stx scorepointers
vblk
; run possible vblank bB code
ifconst vblank_bB_code
jsr vblank_bB_code
endif
vblk2
LDA INTIM
bmi vblk2
jmp kernel
.byte $80,$70,$60,$50,$40,$30,$20,$10,$00
.byte $F0,$E0,$D0,$C0,$B0,$A0,$90
repostable
scorepointerset
and #$0F
asl
asl
asl
adc #<scoretable
tay
txa
; and #$F0
; lsr
asr #$F0
adc #<scoretable
tax
rts
; This is a 2-line kernel!
kernel
sta WSYNC
lda #255
sta TIM64T
lda #1
sta VDELBL
sta VDELP0
ldx ballheight
inx
inx
stx temp4
lda player1y
sta temp3
ifconst shakescreen
jsr doshakescreen
else
ldx missile0height
inx
endif
inx
stx stack1
lda bally
sta stack2
lda player0y
ldx #0
sta WSYNC
stx GRP0
stx GRP1
stx PF1
stx PF2
stx CXCLR
ifconst readpaddle
stx paddle
else
sleep 3
endif
sta temp2,x
;store these so they can be retrieved later
ifnconst pfres
ldx #128-44
else
ldx #132-pfres*4
endif
inc player1y
lda missile0y
sta temp5
lda missile1y
sta temp6
lda playfieldpos
sta temp1
ifconst pfrowheight
lda #pfrowheight+2
else
ifnconst pfres
lda #10
else
lda #(96/pfres)+2 ; try to come close to the real size
endif
endif
clc
sbc playfieldpos
sta playfieldpos
jmp .startkernel
.skipDrawP0
lda #0
tay
jmp .continueP0
.skipDrawP1
lda #0
tay
jmp .continueP1
.kerloop ; enter at cycle 59??
continuekernel
sleep 2
continuekernel2
lda ballheight
ifconst pfres
ldy playfield+pfres*4-132,x
sty PF1 ;3
ldy playfield+pfres*4-131,x
sty PF2 ;3
ldy playfield+pfres*4-129,x
sty PF1 ; 3 too early?
ldy playfield+pfres*4-130,x
sty PF2 ;3
else
ldy playfield+44-128,x ;4
sty PF1 ;3
ldy playfield+45-128,x ;4
sty PF2 ;3
ldy playfield+47-128,x ;4
sty PF1 ; 3 too early?
ldy playfield+46-128,x;4
sty PF2 ;3
endif
dcp bally
rol
rol
; rol
; rol
goback
sta ENABL
.startkernel
lda player1height ;3
dcp player1y ;5
bcc .skipDrawP1 ;2
ldy player1y ;3
lda (player1pointer),y ;5; player0pointer must be selected carefully by the compiler
; so it doesn't cross a page boundary!
.continueP1
sta GRP1 ;3
ifnconst player1colors
lda missile1height ;3
dcp missile1y ;5
rol;2
rol;2
sta ENAM1 ;3
else
lda (player1color),y
sta COLUP1
ifnconst playercolors
sleep 7
else
lda.w player0colorstore
sta COLUP0
endif
endif
ifconst pfres
lda playfield+pfres*4-132,x
sta PF1 ;3
lda playfield+pfres*4-131,x
sta PF2 ;3
lda playfield+pfres*4-129,x
sta PF1 ; 3 too early?
lda playfield+pfres*4-130,x
sta PF2 ;3
else
lda playfield+44-128,x ;4
sta PF1 ;3
lda playfield+45-128,x ;4
sta PF2 ;3
lda playfield+47-128,x ;4
sta PF1 ; 3 too early?
lda playfield+46-128,x;4
sta PF2 ;3
endif
; sleep 3
lda player0height
dcp player0y
bcc .skipDrawP0
ldy player0y
lda (player0pointer),y
.continueP0
sta GRP0
ifnconst no_blank_lines
ifnconst playercolors
lda missile0height ;3
dcp missile0y ;5
sbc stack1
sta ENAM0 ;3
else
lda (player0color),y
sta player0colorstore
sleep 6
endif
dec temp1
bne continuekernel
else
dec temp1
beq altkernel2
ifconst readpaddle
ldy currentpaddle
lda INPT0,y
bpl noreadpaddle
inc paddle
jmp continuekernel2
noreadpaddle
sleep 2
jmp continuekernel
else
ifnconst playercolors
ifconst PFcolors
txa
tay
lda (pfcolortable),y
ifnconst backgroundchange
sta COLUPF
else
sta COLUBK
endif
jmp continuekernel
else
sleep 12
endif
else
lda (player0color),y
sta player0colorstore
sleep 4
endif
jmp continuekernel
endif
altkernel2
txa
sbx #252
bmi lastkernelline
ifconst pfrowheight
lda #pfrowheight
else
ifnconst pfres
lda #8
else
lda #(96/pfres) ; try to come close to the real size
endif
endif
sta temp1
jmp continuekernel
endif
altkernel
ifconst PFmaskvalue
lda #PFmaskvalue
else
lda #0
endif
sta PF1
sta PF2
;sleep 3
;28 cycles to fix things
;minus 11=17
; lax temp4
; clc
txa
sbx #252
bmi lastkernelline
ifconst PFcolorandheight
ldy playfieldcolorandheight-87,x
ifnconst backgroundchange
sty COLUPF
else
sty COLUBK
endif
lda playfieldcolorandheight-88,x
sta.w temp1
endif
ifconst PFheights
lsr
lsr
tay
lda (pfheighttable),y
sta.w temp1
endif
ifconst PFcolors
tay
lda (pfcolortable),y
ifnconst backgroundchange
sta COLUPF
else
sta COLUBK
endif
ifconst pfrowheight
lda #pfrowheight
else
ifnconst pfres
lda #8
else
lda #(96/pfres) ; try to come close to the real size
endif
endif
sta temp1
endif
ifnconst PFcolorandheight
ifnconst PFcolors
ifnconst PFheights
ifnconst no_blank_lines
; read paddle 0
; lo-res paddle read
; bit INPT0
; bmi paddleskipread
; inc paddle0
;donepaddleskip
sleep 10
ifconst pfrowheight
lda #pfrowheight
else
ifnconst pfres
lda #8
else
lda #(96/pfres) ; try to come close to the real size
endif
endif
sta temp1
endif
endif
endif
endif
lda ballheight
dcp bally
sbc temp4
jmp goback
ifnconst no_blank_lines
lastkernelline
ifnconst PFcolors
sleep 10
else
ldy #124
lda (pfcolortable),y
sta COLUPF
endif
ifconst PFheights
ldx #1
sleep 4
else
ldx playfieldpos
sleep 3
endif
jmp enterlastkernel
else
lastkernelline
ifconst PFheights
ldx #1
sleep 5
else
ldx playfieldpos
sleep 4
endif
cpx #1
bne .enterfromNBL
jmp no_blank_lines_bailout
endif
if ((<*)>$d5)
align 256
endif
; this is a kludge to prevent page wrapping - fix!!!
.skipDrawlastP1
sleep 2
lda #0
jmp .continuelastP1
.endkerloop ; enter at cycle 59??
nop
.enterfromNBL
ifconst pfres
ldy.w playfield+pfres*4-4
sty PF1 ;3
ldy.w playfield+pfres*4-3
sty PF2 ;3
ldy.w playfield+pfres*4-1
sty PF1 ; possibly too early?
ldy.w playfield+pfres*4-2
sty PF2 ;3
else
ldy.w playfield+44
sty PF1 ;3
ldy.w playfield+45
sty PF2 ;3
ldy.w playfield+47
sty PF1 ; possibly too early?
ldy.w playfield+46
sty PF2 ;3
endif
enterlastkernel
lda ballheight
; tya
dcp bally
; sleep 4
; sbc stack3
rol
rol
sta ENABL
lda player1height ;3
dcp player1y ;5
bcc .skipDrawlastP1
ldy player1y ;3
lda (player1pointer),y ;5; player0pointer must be selected carefully by the compiler
; so it doesn't cross a page boundary!
.continuelastP1
sta GRP1 ;3
ifnconst player1colors
lda missile1height ;3
dcp missile1y ;5
else
lda (player1color),y
sta COLUP1
endif
dex
;dec temp4 ; might try putting this above PF writes
beq endkernel
ifconst pfres
ldy.w playfield+pfres*4-4
sty PF1 ;3
ldy.w playfield+pfres*4-3
sty PF2 ;3
ldy.w playfield+pfres*4-1
sty PF1 ; possibly too early?
ldy.w playfield+pfres*4-2
sty PF2 ;3
else
ldy.w playfield+44
sty PF1 ;3
ldy.w playfield+45
sty PF2 ;3
ldy.w playfield+47
sty PF1 ; possibly too early?
ldy.w playfield+46
sty PF2 ;3
endif
ifnconst player1colors
rol;2
rol;2
sta ENAM1 ;3
else
ifnconst playercolors
sleep 7
else
lda.w player0colorstore
sta COLUP0
endif
endif
lda.w player0height
dcp player0y
bcc .skipDrawlastP0
ldy player0y
lda (player0pointer),y
.continuelastP0
sta GRP0
ifnconst no_blank_lines
lda missile0height ;3
dcp missile0y ;5
sbc stack1
sta ENAM0 ;3
jmp .endkerloop
else
ifconst readpaddle
ldy currentpaddle
lda INPT0,y
bpl noreadpaddle2
inc paddle
jmp .endkerloop
noreadpaddle2
sleep 4
jmp .endkerloop
else ; no_blank_lines and no paddle reading
sleep 14
jmp .endkerloop
endif
endif
; ifconst donepaddleskip
;paddleskipread
; this is kind of lame, since it requires 4 cycles from a page boundary crossing
; plus we get a lo-res paddle read
; bmi donepaddleskip
; endif
.skipDrawlastP0
sleep 2
lda #0
jmp .continuelastP0
ifconst no_blank_lines
no_blank_lines_bailout
ldx #0
endif
endkernel
; 6 digit score routine
stx PF1
stx PF2
stx PF0
clc
ifconst pfrowheight
lda #pfrowheight+2
else
ifnconst pfres
lda #10
else
lda #(96/pfres)+2 ; try to come close to the real size
endif
endif
sbc playfieldpos
sta playfieldpos
txa
ifconst shakescreen
bit shakescreen
bmi noshakescreen2
ldx #$3D
noshakescreen2
endif
sta WSYNC,x
; STA WSYNC ;first one, need one more
sta REFP0
sta REFP1
STA GRP0
STA GRP1
; STA PF1
; STA PF2
sta HMCLR
sta ENAM0
sta ENAM1
sta ENABL
lda temp2 ;restore variables that were obliterated by kernel
sta player0y
lda temp3
sta player1y
ifnconst player1colors
lda temp6
sta missile1y
endif
ifnconst playercolors
ifnconst readpaddle
lda temp5
sta missile0y
endif
endif
lda stack2
sta bally
ifconst no_blank_lines
sta WSYNC
endif
lda INTIM
clc
ifnconst vblank_time
adc #43+12+87
else
adc #vblank_time+12+87
endif
; sta WSYNC
sta TIM64T
ifconst minikernel
jsr minikernel
endif
; now reassign temp vars for score pointers
; score pointers contain:
; score1-5: lo1,lo2,lo3,lo4,lo5,lo6
; swap lo2->temp1
; swap lo4->temp3
; swap lo6->temp5
ifnconst noscore
lda scorepointers+1
; ldy temp1
sta temp1
; sty scorepointers+1
lda scorepointers+3
; ldy temp3
sta temp3
; sty scorepointers+3
sta HMCLR
tsx
stx stack1
ldx #$10
stx HMP0
sta WSYNC
ldx #0
STx GRP0
STx GRP1 ; seems to be needed because of vdel
lda scorepointers+5
; ldy temp5
sta temp5,x
; sty scorepointers+5
lda #>scoretable
sta scorepointers+1
sta scorepointers+3
sta scorepointers+5,x
sta temp2,x
sta temp4,x
sta temp6,x
LDY #7
STA RESP0
STA RESP1
LDA #$03
STA NUSIZ0
STA NUSIZ1,x
STA VDELP0
STA VDELP1
LDA #$20
STA HMP1
LDA scorecolor
; STA HMCLR
; STA WSYNC; second one
STA HMOVE ; cycle 73 ?
STA COLUP0
STA COLUP1
lda (scorepointers),y
sta GRP0
ifconst pfscore
lda pfscorecolor
sta COLUPF
endif
lda (scorepointers+8),y
sta WSYNC
sleep 2
jmp beginscore
if ((<*)>$d4)
align 256 ; kludge that potentially wastes space! should be fixed!
endif
loop2
lda (scorepointers),y ;+5 68 204
sta GRP0 ;+3 71 213 D1 -- -- --
ifconst pfscore
lda.w pfscore1
sta PF1
else
sleep 7
endif
; cycle 0
lda (scorepointers+$8),y ;+5 5 15
beginscore
sta GRP1 ;+3 8 24 D1 D1 D2 --
lda (scorepointers+$6),y ;+5 13 39
sta GRP0 ;+3 16 48 D3 D1 D2 D2
lax (scorepointers+$2),y ;+5 29 87
txs
lax (scorepointers+$4),y ;+5 36 108
sleep 3
ifconst pfscore
lda pfscore2
sta PF1
else
sleep 6
endif
lda (scorepointers+$A),y ;+5 21 63
stx GRP1 ;+3 44 132 D3 D3 D4 D2!
tsx
stx GRP0 ;+3 47 141 D5 D3! D4 D4
sta GRP1 ;+3 50 150 D5 D5 D6 D4!
sty GRP0 ;+3 53 159 D4* D5! D6 D6
dey
bpl loop2 ;+2 60 180
ldx stack1
txs
; lda scorepointers+1
ldy temp1
; sta temp1
sty scorepointers+1
LDA #0
sta PF1
STA GRP0
STA GRP1
STA VDELP0
STA VDELP1;do we need these
STA NUSIZ0
STA NUSIZ1
; lda scorepointers+3
ldy temp3
; sta temp3
sty scorepointers+3
; lda scorepointers+5
ldy temp5
; sta temp5
sty scorepointers+5
endif ;noscore
LDA #%11000010
sta WSYNC
STA VBLANK
RETURN
ifconst shakescreen
doshakescreen
bit shakescreen
bmi noshakescreen
sta WSYNC
noshakescreen
ldx missile0height
inx
rts
endif
processor 6502
include "vcs.h"
include "macro.h"
include "2600basic_variable_redefs.h"
player0x = $80
player1x = $81
missile0x = $82
missile1x = $83
ballx = $84
objecty = $85
player0y = $85
player1y = $86
missile1height = $87
missile1y = $88
bally = $89
player1color = $87 ; replaces missile 1
player0pointer = $8A ;uses $8A-$8B
player0pointerlo = $8A
player0pointerhi = $8B
player1pointer = $8C ; $8C-$8D
player1pointerlo = $8C
player1pointerhi = $8D
player0height = $8E
player1height = $8F
missile0height = $90
missile0y = $91
ballheight = $92
currentpaddle = $90 ; replaces missile 0 (and can't be used with playercolor)
paddle = $91 ; replaces missile 0
player0colorstore = $82 ; replaces missile 0
player0color = $90 ; replaces missile 0
score = $93 ; $93-$95
scorepointers = $96 ; $96-$9B = 6 bytes
temp1 = $9C ;used by kernel. can be used in program too, but
temp2 = $9D ;are obliterated when drawscreen is called.
temp3 = $9E
temp4 = $9F
temp5 = $A0
temp6 = $A1
rand = $A2
scorecolor = $A3
var0 = $A4
var1 = $A5
var2 = $A6
var3 = $A7
var4 = $A8
var5 = $A9
var6 = $AA
var7 = $AB
var8 = $AC
var9 = $AD
var10 = $AE
var11 = $AF
var12 = $B0
var13 = $B1
var14 = $B2
var15 = $B3
var16 = $B4
var17 = $B5
var18 = $B6
var19 = $B7
var20 = $B8
var21 = $B9
var22 = $BA
var23 = $BB
var24 = $BC
var25 = $BD
var26 = $BE
var27 = $BF
var28 = $C0
var29 = $C1
var30 = $C2
var31 = $C3
var32 = $C4
var33 = $C5
var34 = $C6
var35 = $C7
var36 = $C8
var37 = $C9
var38 = $CA
var39 = $CB
var40 = $CC
var41 = $CD
var42 = $CE
var43 = $CF
var44 = $D0
var45 = $D1
var46 = $D2
var47 = $D3
temp7 = $D4 ; This is used to aid in bankswitching
playfieldpos = $D5
A = $d6
a = $d6
B = $d7
b = $d7
C = $d8
c = $d8
D = $d9
d = $d9
E = $da
e = $da
F = $db
f = $db
G = $dc
g = $dc
H = $dd
h = $dd
I = $de
i = $de
J = $df
j = $df
K = $e0
k = $e0
L = $e1
l = $e1
M = $e2
m = $e2
N = $e3
n = $e3
O = $e4
o = $e4
P = $e5
p = $e5
Q = $e6
q = $e6
R = $e7
r = $e7
S = $e8
s = $e8
T = $e9
t = $e9
U = $ea
u = $ea
V = $eb
v = $eb
W = $ec
w = $ec
X = $ed
x = $ed
Y = $ee
y = $ee
Z = $ef
z = $ef
; available for other uses, or if unused, provide more stack space
aux1 = $f0
aux2 = $f1
aux3 = $f2
aux4 = $f3
aux5 = $f4
aux6 = $f5
; playfield color/height pointers
pfcolortable = $f0 ; and $d5
pfheighttable = $f0 ; and $d5
; the above pointers are the same because if color and height are both used together,
; they must used absolute indexed and cannot use pointers
lifepointer = $f2 ; pointer to "lives" shape
; upper 3 bits of $f2 contain the number of lives
lifecolor = $f4
lives = $f3 ; # lives >> 5
statusbarlength = $f5 ; only uses upper 5 bits; other bits free
pfscore1 = $f2 ; optional playfield bytes in score
pfscore2 = $f3
pfscorecolor = $f4
stack1 = $f6
stack2 = $f7
stack3 = $f8
stack4 = $f9
; the stack bytes above may be used in the kernel
; stack = F6-F7, F8-F9, FA-FB, FC-FD, FE-FF
MAC RETURN ; auto-return from either a regular or bankswitched module
ifnconst bankswitch
rts
else
jmp BS_return
endif
ENDM
ifconst superchip
playfieldbase = $10D0
else
playfieldbase = $A4
endif
; define playfield start based on height
ifnconst pfres
playfield = playfieldbase
else
playfield = playfieldbase-(pfres-12)*4
endif
; every bank has this stuff at the same place
; this code can switch to/from any bank at any entry point
; and can preserve register values
; note: lines not starting with a space are not placed in all banks
;
; line below tells the compiler how long this is - do not remove
;size=32
begin_bscode
ldx #$ff
txs
lda #>(start-1)
pha
lda #<(start-1)
pha
BS_return
pha
txa
pha
tsx
lda 4,x ; get high byte of return address
rol
rol
rol
rol
and #bs_mask ;1 3 or 7 for F8/F6/F4
tax
inx
BS_jsr
lda bankswitch_hotspot-1,x
pla
tax
pla
rts
if ((* & $1FFF) > ((bankswitch_hotspot & $1FFF) - 1))
echo "WARNING: size parameter in banksw.asm too small - the program probably will not work."
echo "Change to",[(*-begin_bscode+1)&$FF]d,"and try again."
endif
processor 6502
include "vcs.h"
include "macro.h"
include "multisprite.h"
include "2600basic_variable_redefs.h"
ifconst bankswitch
if bankswitch == 8
ORG $1000
RORG $D000
endif
if bankswitch == 16
ORG $1000
RORG $9000
endif
if bankswitch == 32
ORG $1000
RORG $1000
endif
else
ORG $F000
endif
; y and a contain multiplicands, result in a
mul8
sty temp1
sta temp2
lda #0
reptmul8
lsr temp2
bcc skipmul8
clc
adc temp1
;bcs donemul8 might save cycles?
skipmul8
;beq donemul8 might save cycles?
asl temp1
bne reptmul8
donemul8
RETURN
div8
; a=numerator y=denominator, result in a
cpy #2
bcc div8end+1;div by 0 = bad, div by 1=no calc needed, so bail out
sty temp1
ldy #$ff
div8loop
sbc temp1
iny
bcs div8loop
div8end
tya
; result in a
RETURN
minikernel ; display up to 6 lives on screen
sta WSYNC
ldx #$20
stx HMP1
stx VDELP0
lda lives
lsr
lsr
lsr
lsr
lsr
sta RESP0
sta RESP1
stx VDELP1
tax
lda lifenusiz0table,x
sta NUSIZ0
lda lifenusiz1table,x
sta NUSIZ1
lda lifecolor
sta COLUP0
sta COLUP1
lda #$10
sta HMP0
lda statusbarlength
lsr
lsr
lsr ; 0-31
; 3 cases: 0-7, 8-15, 16-24
; if 0-7, temp1=val, temp2=0, temp3=0
; if 8-15, temp1=255, temp2=val (rev), temp3=0
; if 16-23, temp1=255, temp2=255, temp3=val
tay
sta HMOVE ;cycle 74?
ifconst statusbarcolor
; only write COLUPF if color variable exists, otherwise use existing PF color
lda statusbarcolor
sta COLUPF
endif
cmp #8
bcc zero_7
cmp #16
bcc eight_15
lda #255
sta temp1
sta temp2
lda statustable-16,y
sta temp3
lda statustable,y
sta temp4
jmp startlifedisplay
zero_7
lda #0
sta temp4
sta temp3
sta temp2
lda statustable,y
sta temp1
jmp startlifedisplay
eight_15
lda #255
sta temp1
lda #0
sta temp4
sta temp3
lda statustable+16,y
sta temp2
startlifedisplay
ldy #7
lifeloop
sta WSYNC
stx PF0
lda (lifepointer),y
cpx #0
bne onelife
.byte $0C
onelife
sta GRP0
cpx #2
bcs nolives
.byte $0C
nolives
sta GRP1
lda temp4
sta PF0
lda temp1
sta PF2
lda temp3
sta PF1
lda temp2
sta PF2 ;cycle 48!
sleep 14
lda #0
dey
sta PF1
bpl lifeloop
sta WSYNC
iny
sty PF0
sty PF2
sty PF1
sty GRP0
sty GRP1
rts
if (<*) > $F5
align 256
endif
lifenusiz1table
.byte 0
lifenusiz0table
.byte 0,0,0,1,1,3,3,3
statustable
;0-7 and 16+
.byte %00000000
.byte %00000001
.byte %00000011
.byte %00000111
.byte %00001111
.byte %00011111
.byte %00111111
.byte %01111111
.byte 255
.byte 255
.byte 255
.byte 255
.byte 255
.byte 255
.byte 255
.byte 255
; 8-15
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte %00000000
.byte %10000000
.byte %11000000
.byte %11100000
.byte %11110000
.byte %11111000
.byte %11111100
.byte %11111110
FineAdjustTableBegin
.byte %01100000 ;left 6
.byte %01010000
.byte %01000000
.byte %00110000
.byte %00100000
.byte %00010000
.byte %00000000 ;left 0
.byte %11110000
.byte %11100000
.byte %11010000
.byte %11000000
.byte %10110000
.byte %10100000
.byte %10010000
.byte %10000000 ;right 8
FineAdjustTableEnd = FineAdjustTableBegin - 241
PFStart
.byte 87,43,0,21,0,0,0,10
blank_pf
.byte 0,0,0,0,0,0,0,5
; .byte 43,21,0,10,0,0,0,5
ifconst screenheight
pfsub
.byte 8,4,2,2,1,0,0,1,0
endif
;--set initial P1 positions
multisprite_setup
lda #15
sta pfheight
ldx #4
; stx temp3
SetCopyHeight
; lda #76
; sta NewSpriteX,X
; lda CopyColorData,X
; sta NewCOLUP1,X
;lda SpriteHeightTable,X
; sta spriteheight,x
txa
sta SpriteGfxIndex,X
sta spritesort,X
dex
bpl SetCopyHeight
; since we can't turn off pf, point PF to zeros here
lda #>blank_pf
sta PF2pointer+1
sta PF1pointer+1
lda #<blank_pf
sta PF2pointer
sta PF1pointer
rts
drawscreen
ifconst debugscore
jsr debugcycles
endif
WaitForOverscanEnd
lda INTIM
bmi WaitForOverscanEnd
lda #2
sta WSYNC
sta VSYNC
sta WSYNC
sta WSYNC
lsr
sta VDELBL
sta VDELP0
sta WSYNC
sta VSYNC ;turn off VSYNC
ifconst overscan_time
lda #overscan_time+5+128
else
lda #42+128
endif
sta TIM64T
jsr setscorepointers
jsr SetupP1Subroutine
;-------------
;--position P0, M0, M1, BL
jsr PrePositionAllObjects
;--set up player 0 pointer
lda player0pointer ; player0: must be run every frame!
sec
sbc player0y
clc
adc player0height
sta player0pointer
lda player0y
sta P0Top
sec
sbc player0height
clc
adc #$80
sta P0Bottom
;--some final setup
ldx #4
lda #$80
cycle74_HMCLR
sta HMP0,X
dex
bpl cycle74_HMCLR
; sta HMCLR
lda #0
sta PF1
sta PF2
sta GRP0
sta GRP1
jsr KernelSetupSubroutine
; run possible vblank bB code
ifconst vblank_bB_code
jsr vblank_bB_code
endif
WaitForVblankEnd
lda INTIM
bmi WaitForVblankEnd
lda #0
sta WSYNC
sta VBLANK ;turn off VBLANK - it was turned on by overscan
sta CXCLR
jmp KernelRoutine
PositionASpriteSubroutine ;call this function with A == horizontal position (0-159)
;and X == the object to be positioned (0=P0, 1=P1, 2=M0, etc.)
;if you do not wish to write to P1 during this function, make
;sure Y==0 before you call it. This function will change Y, and A
;will be the value put into HMxx when returned.
;Call this function with at least 11 cycles left in the scanline
;(jsr + sec + sta WSYNC = 11); it will return 9 cycles
;into the second scanline
sec
sta WSYNC ;begin line 1
sta.w HMCLR ;+4 4
DivideBy15Loop
sbc #15
bcs DivideBy15Loop ;+4/5 8/13.../58
tay ;+2 10/15/...60
lda FineAdjustTableEnd,Y ;+5 15/20/...65
; 15
sta HMP0,X ;+4 19/24/...69
sta RESP0,X ;+4 23/28/33/38/43/48/53/58/63/68/73
sta WSYNC ;+3 0 begin line 2
sta HMOVE ;+3
rts ;+6 9
;-------------------------------------------------------------------------
PrePositionAllObjects
ldx #4
lda ballx
jsr PositionASpriteSubroutine
dex
lda missile1x
jsr PositionASpriteSubroutine
dex
lda missile0x
jsr PositionASpriteSubroutine
dex
dex
lda player0x
jsr PositionASpriteSubroutine
rts
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
KernelSetupSubroutine
ldx #4
AdjustYValuesUpLoop
lda NewSpriteY,X
clc
adc #2
sta NewSpriteY,X
dex
bpl AdjustYValuesUpLoop
ldx temp3 ; first sprite displayed
lda SpriteGfxIndex,x
tay
lda NewSpriteY,y
sta RepoLine
lda SpriteGfxIndex-1,x
tay
lda NewSpriteY,y
sta temp6
stx SpriteIndex
lda #255
sta P1Bottom
lda player0y
ifconst screenheight
cmp #screenheight+1
else
cmp #$59
endif
bcc nottoohigh
lda P0Bottom
sta P0Top
nottoohigh
rts
;-------------------------------------------------------------------------
;*************************************************************************
;-------------------------------------------------------------------------
;-------------------------Data Below--------------------------------------
;-------------------------------------------------------------------------
MaskTable
.byte 1,3,7,15,31
; shove 6-digit score routine here
sixdigscore
lda #0
; sta COLUBK
sta PF0
sta PF1
sta PF2
sta ENABL
sta ENAM0
sta ENAM1
;end of kernel here
; 6 digit score routine
; lda #0
; sta PF1
; sta PF2
; tax
sta WSYNC;,x
; STA WSYNC ;first one, need one more
sta REFP0
sta REFP1
STA GRP0
STA GRP1
sta HMCLR
; restore P0pointer
lda player0pointer
clc
adc player0y
sec
sbc player0height
sta player0pointer
ifconst vblank_time
ifconst screenheight
if screenheight == 84
lda #vblank_time+9+128+10
else
lda #vblank_time+9+128+19
endif
else
lda #vblank_time+9+128
endif
else
ifconst screenheight
if screenheight == 84
lda #52+128+10
else
lda #52+128+19
endif
else
lda #52+128
endif
endif
sta TIM64T
ifconst minikernel
jsr minikernel
endif
ifconst noscore
jmp skipscore
endif
; score pointers contain:
; score1-5: lo1,lo2,lo3,lo4,lo5,lo6
; swap lo2->temp1
; swap lo4->temp3
; swap lo6->temp5
lda scorepointers+5
sta temp5
lda scorepointers+1
sta temp1
lda scorepointers+3
sta temp3
lda #>scoretable
sta scorepointers+1
sta scorepointers+3
sta scorepointers+5
sta temp2
sta temp4
sta temp6
rts
;-------------------------------------------------------------------------
;----------------------Kernel Routine-------------------------------------
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; echo *
; repeat $f147-*
; brk
; repend
; org $F240
SwitchDrawP0K1 ; 72
lda P0Bottom
sta P0Top ;+6 2
jmp BackFromSwitchDrawP0K1 ;+3 5
WaitDrawP0K1 ; 74
SLEEP 4 ;+4 2
jmp BackFromSwitchDrawP0K1 ;+3 5
SkipDrawP1K1 ; 11
lda #0
sta GRP1 ;+5 16 so Ball gets drawn
jmp BackFromSkipDrawP1 ;+3 19
;-------------------------------------------------------------------------
KernelRoutine
ifnconst screenheight
jsr wastetime ; waste 12 cycles
else
sleep 6
endif
tsx
stx stack1
ldx #ENABL
txs ;+9 9
ldx #0
lda pfheight
bpl asdhj
.byte $24
asdhj
tax
; ldx pfheight
lda PFStart,x ; get pf pixel resolution for heights 15,7,3,1,0
ifconst screenheight
sec
if screenheight == 84
sbc pfsub+1,x
else
sbc pfsub,x
endif
endif
sta pfpixelheight
ifconst screenheight
ldy #screenheight
else
ldy #88
endif
; lda #$02
; sta COLUBK ;+5 18
; sleep 25
sleep 2
KernelLoopa ; 50
SLEEP 7 ;+4 54
KernelLoopb ; 54
SLEEP 2 ;+12 66
cpy P0Top ;+3 69
beq SwitchDrawP0K1 ;+2 71
bpl WaitDrawP0K1 ;+2 73
lda (player0pointer),Y ;+5 2
sta GRP0 ;+3 5 VDEL because of repokernel
BackFromSwitchDrawP0K1
cpy P1Bottom ;+3 8 unless we mean to draw immediately, this should be set
; to a value greater than maximum Y value initially
bcc SkipDrawP1K1 ;+2 10
lda (P1display),Y ;+5 15
sta.w GRP1 ;+4 19
BackFromSkipDrawP1
;fuck
sty temp1
ldy pfpixelheight
lax (PF1pointer),y
stx PF1 ;+7 26
lda (PF2pointer),y
sta PF2 ;+7 33
;sleep 6
stx PF1temp2
sta PF2temp2
dey
lda (PF1pointer),y
sta PF1temp1
lda (PF2pointer),y
sta PF2temp1
ldy temp1
ldx #ENABL
txs
cpy bally
php ;+6 39 VDEL ball
cpy missile1y
php ;+6 71
cpy missile0y
php ;+6 1
ldx #1
dey ;+2 15
cpy RepoLine ;+3 18
beq RepoKernel ;+2 20
; SLEEP 20 ;+23 43
sleep 6
newrepo ; since we have time here, store next repoline
ldx SpriteIndex
lda SpriteGfxIndex-1,x
tax
lda NewSpriteY,x
sta temp6
sleep 4
BackFromRepoKernel
tya ;+2 45
and pfheight ;+2 47
bne KernelLoopa ;+2 49
dec pfpixelheight
bpl KernelLoopb ;+3 54
; bmi donewkernel ;+3 54
; bne KernelLoopb+1 ;+3 54
donewkernel
jmp DoneWithKernel ;+3 56
;-------------------------------------------------------------------------
; room here for score?
setscorepointers
lax score+2
jsr scorepointerset
sty scorepointers+5
stx scorepointers+2
lax score+1
jsr scorepointerset
sty scorepointers+4
stx scorepointers+1
lax score
jsr scorepointerset
sty scorepointers+3
stx scorepointers
wastetime
rts
scorepointerset
and #$0F
asl
asl
asl
adc #<scoretable
tay
txa
and #$F0
lsr
adc #<scoretable
tax
rts
; align 256
SwitchDrawP0KR ; 45
lda P0Bottom
sta P0Top ;+6 51
jmp BackFromSwitchDrawP0KR ;+3 54
WaitDrawP0KR ; 47
SLEEP 4 ;+4 51
jmp BackFromSwitchDrawP0KR ;+3 54
;-----------------------------------------------------------
noUpdateXKR
sleep 3
JMP retXKR
skipthis
ldx #1
; sleep 2
jmp goback
RepoKernel ; 22 crosses page boundary
tya
and pfheight ;+2 26
bne noUpdateXKR ;+2 28
dex ;+2 30
dec pfpixelheight
; stx Temp ;+3 35
; SLEEP 3
retXKR
cpy P0Top ;+3 42
beq SwitchDrawP0KR ;+2 44
bpl WaitDrawP0KR ;+2 46
lda (player0pointer),Y ;+5 51
sta GRP0 ;+3 54 VDEL
BackFromSwitchDrawP0KR
sec ;+2 56
lda PF2temp1,X
ldy PF1temp1,X
ldx SpriteIndex ;+3 2
sta PF2 ;+7 63
lda SpriteGfxIndex,x
sty PF1 ;+7 70 too early?
tax
lda #0
sta GRP1 ;+5 75 to display player 0
lda NewSpriteX,X ;+4 6
DivideBy15LoopK ; 6 (carry set above)
sbc #15
bcs DivideBy15LoopK ;+4/5 10/15.../60
tax ;+2 12/17/...62
lda FineAdjustTableEnd,X ;+5 17/22/...67
sta HMP1 ;+3 20/25/...70
sta RESP1 ;+3 23/28/33/38/43/48/53/58/63/68/73
sta WSYNC ;+3 0 begin line 2
;sta HMOVE ;+3 3
ldx #ENABL
txs ;+4 25
ldy RepoLine ; restore y
cpy bally
php ;+6 9 VDEL ball
cpy missile1y
php ;+6 15
cpy missile0y
php ;+6 21
;15 cycles
tya
and pfheight
;eor #1
and #$FE
bne skipthis
tax
sleep 4
; sleep 2
goback
dey
cpy P0Top ;+3 52
beq SwitchDrawP0KV ;+2 54
bpl WaitDrawP0KV ;+2 56
lda (player0pointer),Y ;+5 61
sta GRP0 ;+3 64 VDEL
BackFromSwitchDrawP0KV
; sleep 3
lda PF2temp1,X
sta PF2 ;+7 5
lda PF1temp1,X
sta PF1 ;+7 74
sta HMOVE
lda #0
sta GRP1 ;+5 10 to display GRP0
ldx #ENABL
txs ;+4 8
ldx SpriteIndex ;+3 13 restore index into new sprite vars
;--now, set all new variables and return to main kernel loop
;
lda SpriteGfxIndex,X ;+4 31
tax ;+2 33
;
lda NewSpriteY,X ;+4 46
sta P1Bottom ;+3 49 adjust for height below
lda NewNUSIZ,X
sta NUSIZ1 ;+7 20
sta REFP1
lda NewCOLUP1,X
sta COLUP1 ;+7 27
; lda SpriteGfxIndex,X ;+4 31
; tax ;+2 33
;fuck2
lda P1Bottom ;+3 36
sec ;+2 38
sbc spriteheight,X ;+4 42
sta P1Bottom ;+3 45
lda player1pointerlo,X ;+4 49
sbc P1Bottom ;+3 52 carry should still be set
sta P1display ;+3 55
lda player1pointerhi,X
sta P1display+1 ;+7 62
cpy bally
php ;+6 68 VDELed
cpy missile1y
php ;+6 74
cpy missile0y
php ;+6 4
; lda SpriteGfxIndex-1,x
; sleep 3
dec SpriteIndex ;+5 13
; tax
; lda NewSpriteY,x
; sta RepoLine
; 10 cycles below...
bpl SetNextLine
lda #255
jmp SetLastLine
SetNextLine
; lda NewSpriteY-1,x
lda.w temp6
SetLastLine
sta RepoLine
tya
and pfheight
bne nodec
dec pfpixelheight
dey ;+2 30
; 10 cycles
jmp BackFromRepoKernel ;+3 43
nodec
sleep 4
dey
jmp BackFromRepoKernel
;-------------------------------------------------------------------------
SwitchDrawP0KV ; 69
lda P0Bottom
sta P0Top ;+6 75
jmp BackFromSwitchDrawP0KV ;+3 2
WaitDrawP0KV ; 71
SLEEP 4 ;+4 75
jmp BackFromSwitchDrawP0KV ;+3 2
;-------------------------------------------------------------------------
DoneWithKernel
BottomOfKernelLoop
sta WSYNC
ldx stack1
txs
jsr sixdigscore ; set up score
sta WSYNC
ldx #0
sta HMCLR
STx GRP0
STx GRP1 ; seems to be needed because of vdel
LDY #7
STy VDELP0
STy VDELP1
LDA #$10
STA HMP1
LDA scorecolor
STA COLUP0
STA COLUP1
LDA #$03
STA NUSIZ0
STA NUSIZ1
STA RESP0
STA RESP1
sleep 9
lda (scorepointers),y
sta GRP0
ifconst pfscore
lda pfscorecolor
sta COLUPF
else
sleep 6
endif
STA HMOVE
lda (scorepointers+8),y
; sta WSYNC
;sleep 2
jmp beginscore
loop2
lda (scorepointers),y ;+5 68 204
sta GRP0 ;+3 71 213 D1 -- -- --
ifconst pfscore
lda.w pfscore1
sta PF1
else
sleep 7
endif
; cycle 0
lda (scorepointers+$8),y ;+5 5 15
beginscore
sta GRP1 ;+3 8 24 D1 D1 D2 --
lda (scorepointers+$6),y ;+5 13 39
sta GRP0 ;+3 16 48 D3 D1 D2 D2
lax (scorepointers+$2),y ;+5 29 87
txs
lax (scorepointers+$4),y ;+5 36 108
sleep 3
ifconst pfscore
lda pfscore2
sta PF1
else
sleep 6
endif
lda (scorepointers+$A),y ;+5 21 63
stx GRP1 ;+3 44 132 D3 D3 D4 D2!
tsx
stx GRP0 ;+3 47 141 D5 D3! D4 D4
sta GRP1 ;+3 50 150 D5 D5 D6 D4!
sty GRP0 ;+3 53 159 D4* D5! D6 D6
dey
bpl loop2 ;+2 60 180
ldx stack1
txs
; lda scorepointers+1
ldy temp1
; sta temp1
sty scorepointers+1
LDA #0
STA GRP0
STA GRP1
sta PF1
STA VDELP0
STA VDELP1;do we need these
STA NUSIZ0
STA NUSIZ1
; lda scorepointers+3
ldy temp3
; sta temp3
sty scorepointers+3
; lda scorepointers+5
ldy temp5
; sta temp5
sty scorepointers+5
;-------------------------------------------------------------------------
;------------------------Overscan Routine---------------------------------
;-------------------------------------------------------------------------
OverscanRoutine
skipscore
lda #2
sta WSYNC
sta VBLANK ;turn on VBLANK
;-------------------------------------------------------------------------
;----------------------------End Main Routines----------------------------
;-------------------------------------------------------------------------
;*************************************************************************
;-------------------------------------------------------------------------
;----------------------Begin Subroutines----------------------------------
;-------------------------------------------------------------------------
KernelCleanupSubroutine
ldx #4
AdjustYValuesDownLoop
lda NewSpriteY,X
sec
sbc #2
sta NewSpriteY,X
dex
bpl AdjustYValuesDownLoop
RETURN
;rts
SetupP1Subroutine
; flickersort algorithm
; count 4-0
; table2=table1 (?)
; detect overlap of sprites in table 2
; if overlap, do regular sort in table2, then place one sprite at top of table 1, decrement # displayed
; if no overlap, do regular sort in table 2 and table 1
ldx #255
copytable
inx
lda spritesort,x
sta SpriteGfxIndex,x
cpx #4
bne copytable
stx temp3 ; highest displayed sprite
dex
stx temp2
sortloop
ldx temp2
lda spritesort,x
tax
lda NewSpriteY,x
sta temp1
ldx temp2
lda spritesort+1,x
tax
lda NewSpriteY,x
sec
sbc temp1
bcc largerXislower
; larger x is higher (A>=temp1)
cmp spriteheight,x
bcs countdown
; overlap with x+1>x
;
; stick x at end of gfxtable, dec counter
overlapping
dec temp3
ldx temp2
inx
jsr shiftnumbers
jmp skipswapGfxtable
largerXislower ; (temp1>A)
tay
ldx temp2
lda spritesort,x
tax
tya
eor #$FF
cmp spriteheight,x
bcs notoverlapping
dec temp3
ldx temp2
inx
jsr shiftnumbers
jmp skipswapGfxtable
notoverlapping
ldx temp2 ; swap display table
ldy SpriteGfxIndex+1,x
lda SpriteGfxIndex,x
sty SpriteGfxIndex,x
sta SpriteGfxIndex+1,x
skipswapGfxtable
ldx temp2 ; swap sort table
ldy spritesort+1,x
lda spritesort,x
sty spritesort,x
sta spritesort+1,x
countdown
dec temp2
bpl sortloop
checktoohigh
ldx temp3
lda SpriteGfxIndex,x
tax
lda NewSpriteY,x
ifconst screenheight
cmp #screenheight-2
else
cmp #$56
endif
bcc nonetoohigh
dec temp3
bne checktoohigh
nonetoohigh
rts
shiftnumbers
; stick current x at end, shift others down
; if x=4: don't do anything
; if x=3: swap 3 and 4
; if x=2: 2=3, 3=4, 4=2
; if x=1: 1=2, 2=3, 3=4, 4=1
; if x=0: 0=1, 1=2, 2=3, 3=4, 4=0
ldy SpriteGfxIndex,x
swaploop
cpx #4
beq shiftdone
lda SpriteGfxIndex+1,x
sta SpriteGfxIndex,x
inx
jmp swaploop
shiftdone
sty SpriteGfxIndex,x
rts
ifconst debugscore
debugcycles
ldx #14
lda INTIM ; display # cycles left in the score
ifconst mincycles
lda mincycles
cmp INTIM
lda mincycles
bcc nochange
lda INTIM
sta mincycles
nochange
endif
; cmp #$2B
; bcs no_cycles_left
bmi cycles_left
ldx #64
eor #$ff ;make negative
cycles_left
stx scorecolor
and #$7f ; clear sign bit
tax
lda scorebcd,x
sta score+2
lda scorebcd1,x
sta score+1
rts
scorebcd
.byte $00, $64, $28, $92, $56, $20, $84, $48, $12, $76, $40
.byte $04, $68, $32, $96, $60, $24, $88, $52, $16, $80, $44
.byte $08, $72, $36, $00, $64, $28, $92, $56, $20, $84, $48
.byte $12, $76, $40, $04, $68, $32, $96, $60, $24, $88
scorebcd1
.byte 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6
.byte 7, 7, 8, 8, 9, $10, $10, $11, $12, $12, $13
.byte $14, $14, $15, $16, $16, $17, $17, $18, $19, $19, $20
.byte $21, $21, $22, $23, $23, $24, $24, $25, $26, $26
endif
;
; Inclues go below - order is crucial, since this is also the order in which
; they will appear in the generated assembly file
;
; header file
2600basicheader.asm
; standard kernel: two players, two missiles, a ball and an asymmetric playfield.
std_kernel.asm
; standard startup routine.
startup.asm
; below are collections of subroutines and functions
; if you have any more to add, put them immediately below this line.
pf_drawing.asm
pf_scrolling.asm
std_routines.asm
; The overscan routine goes below. it sets up sprites for the std_kernel.
; if you have any routines that will not run until the overscan period,
; put them immediately below this line.
std_overscan.asm
; below is the generated batari Basic file
bB.asm
; score graphics.
score_graphics.asm
; below is the footer, which contains the score digits and startup vectors.
; If you want to create your own custom score digits, you may hack the file below,
; but first you should rename it to something else.
2600basicfooter.asm
processor 6502
include "vcs.h"
include "macro.h"
include "2600basic.h"
include "2600basic_variable_redefs.h"
ifconst bankswitch
if bankswitch == 8
ORG $1000
RORG $D000
endif
if bankswitch == 16
ORG $1000
RORG $9000
endif
if bankswitch == 32
ORG $1000
RORG $1000
endif
else
ORG $F000
endif
repeat 256
.byte $ff
repend
pfscroll ;(a=0 left, 1 right, 2 up, 4 down, 6=upup, 12=downdown)
bne notleft
;left
ifconst pfres
ldx #pfres*4
else
ldx #48
endif
leftloop
lda playfield-1,x
lsr
ifconst superchip
lda playfield-2,x
rol
sta playfield-130,x
lda playfield-3,x
ror
sta playfield-131,x
lda playfield-4,x
rol
sta playfield-132,x
lda playfield-1,x
ror
sta playfield-129,x
else
rol playfield-2,x
ror playfield-3,x
rol playfield-4,x
ror playfield-1,x
endif
txa
sbx #4
bne leftloop
RETURN
notleft
lsr
bcc notright
;right
ifconst pfres
ldx #pfres*4
else
ldx #48
endif
rightloop
lda playfield-4,x
lsr
ifconst superchip
lda playfield-3,x
rol
sta playfield-131,x
lda playfield-2,x
ror
sta playfield-130,x
lda playfield-1,x
rol
sta playfield-129,x
lda playfield-4,x
ror
sta playfield-132,x
else
rol playfield-3,x
ror playfield-2,x
rol playfield-1,x
ror playfield-4,x
endif
txa
sbx #4
bne rightloop
RETURN
notright
lsr
bcc notup
;up
lsr
bcc onedecup
dec playfieldpos
onedecup
dec playfieldpos
beq shiftdown
bpl noshiftdown2
shiftdown
ifconst pfrowheight
lda #pfrowheight
else
ifnconst pfres
lda #8
else
lda #(96/pfres) ; try to come close to the real size
endif
endif
sta playfieldpos
lda playfield+3
sta temp4
lda playfield+2
sta temp3
lda playfield+1
sta temp2
lda playfield
sta temp1
ldx #0
up2
lda playfield+4,x
ifconst superchip
sta playfield-128,x
lda playfield+5,x
sta playfield-127,x
lda playfield+6,x
sta playfield-126,x
lda playfield+7,x
sta playfield-125,x
else
sta playfield,x
lda playfield+5,x
sta playfield+1,x
lda playfield+6,x
sta playfield+2,x
lda playfield+7,x
sta playfield+3,x
endif
txa
sbx #252
ifconst pfres
cpx #(pfres-1)*4
else
cpx #44
endif
bne up2
lda temp4
ifconst superchip
ifconst pfres
sta playfield+pfres*4-129
lda temp3
sta playfield+pfres*4-130
lda temp2
sta playfield+pfres*4-131
lda temp1
sta playfield+pfres*4-132
else
sta playfield+47-128
lda temp3
sta playfield+46-128
lda temp2
sta playfield+45-128
lda temp1
sta playfield+44-128
endif
else
ifconst pfres
sta playfield+pfres*4-1
lda temp3
sta playfield+pfres*4-2
lda temp2
sta playfield+pfres*4-3
lda temp1
sta playfield+pfres*4-4
else
sta playfield+47
lda temp3
sta playfield+46
lda temp2
sta playfield+45
lda temp1
sta playfield+44
endif
endif
noshiftdown2
RETURN
notup
;down
lsr
bcs oneincup
inc playfieldpos
oneincup
inc playfieldpos
lda playfieldpos
ifconst pfrowheight
cmp #pfrowheight+1
else
ifnconst pfres
cmp #9
else
cmp #(96/pfres)+1 ; try to come close to the real size
endif
endif
bcc noshiftdown
lda #1
sta playfieldpos
ifconst pfres
lda playfield+pfres*4-1
sta temp4
lda playfield+pfres*4-2
sta temp3
lda playfield+pfres*4-3
sta temp2
lda playfield+pfres*4-4
else
lda playfield+47
sta temp4
lda playfield+46
sta temp3
lda playfield+45
sta temp2
lda playfield+44
endif
sta temp1
ifconst pfres
ldx #(pfres-1)*4
else
ldx #44
endif
down2
lda playfield-1,x
ifconst superchip
sta playfield-125,x
lda playfield-2,x
sta playfield-126,x
lda playfield-3,x
sta playfield-127,x
lda playfield-4,x
sta playfield-128,x
else
sta playfield+3,x
lda playfield-2,x
sta playfield+2,x
lda playfield-3,x
sta playfield+1,x
lda playfield-4,x
sta playfield,x
endif
txa
sbx #4
bne down2
lda temp4
ifconst superchip
sta playfield-125
lda temp3
sta playfield-126
lda temp2
sta playfield-127
lda temp1
sta playfield-128
else
sta playfield+3
lda temp3
sta playfield+2
lda temp2
sta playfield+1
lda temp1
sta playfield
endif
noshiftdown
RETURN
;standard routines needed for pretty much all games
; just the random number generator is left - maybe we should remove this asm file altogether?
; repositioning code and score pointer setup moved to overscan
; read switches, joysticks now compiler generated (more efficient)
randomize
lda rand
lsr
ifconst rand16
rol rand16
endif
bcc noeor
eor #$B4
noeor
sta rand
ifconst rand16
eor rand16
endif
RETURN
processor 6502
include "vcs.h"
include "macro.h"
include "2600basic.h"
include "2600basic_variable_redefs.h"
ifconst bankswitch
if bankswitch == 8
ORG $1000
RORG $D000
endif
if bankswitch == 16
ORG $1000
RORG $9000
endif
if bankswitch == 32
ORG $1000
RORG $1000
endif
else
ORG $F000
endif
;
; Inclues go below - order is crucial, since this is also the order in which
; they will appear in the generated assembly file
;
; header file
multispriteheader.asm
; this is the batari Basic file
; for bankswitching, the concatenator will only parse until the end of
; bank 1
bB.asm
; standard kernel: two players, two missiles, a ball and an asymmetric playfield.
multisprite_kernel.asm
; standard startup routine.
startup.asm
; below are collections of subroutines and functions
; if you have any more to add, put them immediately below this line.
std_routines.asm
; below is the generated batari Basic file
; note: this file is generated by the concatenation program.
; automatically split off from the bB.asm file where the new bank occurs
bB2.asm
; score gfx
score_graphics.asm
;bankswitch support
banksw.asm
; below is the footer, which contains the score digits and startup vectors.
; If you want to create your own custom score digits, you may hack the file below,
; but first you should rename it to something else.
; also includes bankswitching support (if applicable)
2600basicfooter.asm
start
sei
cld
ldy #0
lda $D0
cmp #$2C ;check RAM location #1
bne MachineIs2600
lda $D1
cmp #$A9 ;check RAM location #2
bne MachineIs2600
dey
MachineIs2600
ldx #0
txa
clearmem
inx
txs
pha
bne clearmem
sty temp1
ifconst pfrowheight
lda pfrowheight
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
; playfield drawing routines
; you get a 32x12 bitmapped display in a single color :)
; 0-31 and 0-11
pfclear ; clears playfield - or fill with pattern
ifconst pfres
ldx #pfres*4-1
else
ldx #47
endif
pfclear_loop
ifnconst superchip
sta playfield,x
else
sta playfield-128,x
endif
dex
bpl pfclear_loop
RETURN
setuppointers
stx temp2 ; store on.off.flip value
tax ; put x-value in x
lsr
lsr
lsr ; divide x pos by 8
sta temp1
tya
asl
asl ; multiply y pos by 4
clc
adc temp1 ; add them together to get actual memory location offset
tay ; put the value in y
lda temp2 ; restore on.off.flip value
rts
pfread
;x=xvalue, y=yvalue
jsr setuppointers
lda setbyte,x
and playfield,y
eor setbyte,x
; beq readzero
; lda #1
; readzero
RETURN
pfpixel
;x=xvalue, y=yvalue, a=0,1,2
jsr setuppointers
ifconst bankswitch
lda temp2 ; load on.off.flip value (0,1, or 2)
beq pixelon_r ; if "on" go to on
lsr
bcs pixeloff_r ; value is 1 if true
lda playfield,y ; if here, it's "flip"
eor setbyte,x
ifconst superchip
sta playfield-128,y
else
sta playfield,y
endif
RETURN
pixelon_r
lda playfield,y
ora setbyte,x
ifconst superchip
sta playfield-128,y
else
sta playfield,y
endif
RETURN
pixeloff_r
lda setbyte,x
eor #$ff
and playfield,y
ifconst superchip
sta playfield-128,y
else
sta playfield,y
endif
RETURN
else
jmp plotpoint
endif
pfhline
;x=xvalue, y=yvalue, a=0,1,2, temp3=endx
jsr setuppointers
jmp noinc
keepgoing
inx
txa
and #7
bne noinc
iny
noinc
jsr plotpoint
cpx temp3
bmi keepgoing
RETURN
pfvline
;x=xvalue, y=yvalue, a=0,1,2, temp3=endx
jsr setuppointers
sty temp1 ; store memory location offset
inc temp3 ; increase final x by 1
lda temp3
asl
asl ; multiply by 4
sta temp3 ; store it
; Thanks to Michael Rideout for fixing a bug in this code
; right now, temp1=y=starting memory location, temp3=final
; x should equal original x value
keepgoingy
jsr plotpoint
iny
iny
iny
iny
cpy temp3
bmi keepgoingy
RETURN
plotpoint
lda temp2 ; load on.off.flip value (0,1, or 2)
beq pixelon ; if "on" go to on
lsr
bcs pixeloff ; value is 1 if true
lda playfield,y ; if here, it's "flip"
eor setbyte,x
ifconst superchip
sta playfield-128,y
else
sta playfield,y
endif
rts
pixelon
lda playfield,y
ora setbyte,x
ifconst superchip
sta playfield-128,y
else
sta playfield,y
endif
rts
pixeloff
lda setbyte,x
eor #$ff
and playfield,y
ifconst superchip
sta playfield-128,y
else
sta playfield,y
endif
rts
setbyte
.byte $80
.byte $40
.byte $20
.byte $10
.byte $08
.byte $04
.byte $02
.byte $01
.byte $01
.byte $02
.byte $04
.byte $08
.byte $10
.byte $20
.byte $40
.byte $80
.byte $80
.byte $40
.byte $20
.byte $10
.byte $08
.byte $04
.byte $02
.byte $01
.byte $01
.byte $02
.byte $04
.byte $08
.byte $10
.byte $20
.byte $40
.byte $80
; feel free to modify the score graphics - just keep each digit 8 high
; and keep the conditional compilation stuff intact
ifconst ROM2k
ORG $F7AC
else
ifconst bankswitch
if bankswitch == 8
ORG $2F94-bscode_length
RORG $FF94-bscode_length
endif
if bankswitch == 16
ORG $4F94-bscode_length
RORG $FF94-bscode_length
endif
if bankswitch == 32
ORG $8F94-bscode_length
RORG $FF94-bscode_length
endif
else
ORG $FF9C
endif
endif
scoretable
.byte %00111100
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %00111100
.byte %01111110
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00111000
.byte %00011000
.byte %00001000
.byte %01111110
.byte %01100000
.byte %01100000
.byte %00111100
.byte %00000110
.byte %00000110
.byte %01000110
.byte %00111100
.byte %00111100
.byte %01000110
.byte %00000110
.byte %00000110
.byte %00011100
.byte %00000110
.byte %01000110
.byte %00111100
.byte %00001100
.byte %00001100
.byte %01111110
.byte %01001100
.byte %01001100
.byte %00101100
.byte %00011100
.byte %00001100
.byte %00111100
.byte %01000110
.byte %00000110
.byte %00000110
.byte %00111100
.byte %01100000
.byte %01100000
.byte %01111110
.byte %00111100
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01111100
.byte %01100000
.byte %01100010
.byte %00111100
.byte %00110000
.byte %00110000
.byte %00110000
.byte %00011000
.byte %00001100
.byte %00000110
.byte %01000010
.byte %00111110
.byte %00111100
.byte %01100110
.byte %01100110
.byte %01100110
.byte %00111100
.byte %01100110
.byte %01100110
.byte %00111100
.byte %00111100
.byte %01000110
.byte %00000110
.byte %00111110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %00111100
ifconst ROM2k
ORG $F7FC
else
ifconst bankswitch
if bankswitch == 8
ORG $2FF4-bscode_length
RORG $FFF4-bscode_length
endif
if bankswitch == 16
ORG $4FF4-bscode_length
RORG $FFF4-bscode_length
endif
if bankswitch == 32
ORG $8FF4-bscode_length
RORG $FFF4-bscode_length
endif
else
ORG $FFFC
endif
endif
pfread
cmp #16
bcc lefthalf
eor #31 ; 16-31 converted to 15-0
lefthalf
tax
lda bytemask,x
cpx #8
bcc bytedone
and (PF2pointer),y
.byte $0C
bytedone
and (PF1pointer),y
RETURN
bytemask
.byte $80,$40,$20,$10,8,4,2,1
.byte 1,2,4,8,$10,$20,$40,$80
; Fixed point math routines - created by AtariAge member djmips
; some changes by Fred Quimby
;assignment from 8.8 to 4.4
Assign88to44:
; A(4.4) = A,X(8.8)
stx temp1
rol temp1
asl
rol temp1
asl
rol temp1
asl
rol temp1
asl
rts
;assignment from 4.4 to 8.8
;
Assign44to88:
; A,X(8.8) = A(4.4)
sta temp1
lda #0
asl temp1
sbc #0 ;
eor #$ff ; do sign extend
rol
asl temp1
rol
asl temp1
rol
asl temp1
rol
ldx temp1
rts
ifconst bankswitch
Assign88to44bs:
; A(4.4) = A,X(8.8)
stx temp1
rol temp1
asl
rol temp1
asl
rol temp1
asl
rol temp1
asl
RETURN
;assignment from 4.4 to 8.8
;
Assign44to88bs:
; A,X(8.8) = A(4.4)
sta temp1
lda #0
asl temp1
sbc #0 ;
eor #$ff ; do sign extend
rol
asl temp1
rol
asl temp1
rol
asl temp1
rol
ldx temp1
RETURN
endif
;
;Addition/subtraction asm procedures:
;add/sub 8.8 to/from 4.4
Add88to44:
; A(4.4) = A,X(8.8) + Y(4.4)
jsr Assign88to44
sty temp1
clc
adc temp1
rts
Sub88from44:
; A(4.4) = A,X(8.8) - Y(4.4)
jsr Assign88to44
sty temp1
sec
sbc temp1
rts
Add44to88:
; A,X(8.8) = A,X(8.8) + Y(4.4)
sta temp2
stx temp3
tya
jsr Assign44to88
clc
sta temp1
txa
adc temp3
tax
lda temp1
adc temp2
rts
Sub44from88:
; A,X(8.8) = A,X(8.8) - Y(4.4)
sta temp2
stx temp3
tya
jsr Assign44to88
sec
sta temp1
lda temp3
stx temp3
sbc temp3
tax
lda temp2
sbc temp1
rts
missile0x = $80
missile1x = $81
ballx = $82
objecty = $83
missile0y = $83
missile1y = $84
bally = $85
; multisprite stuff below - 5 bytes each starting with spritex
SpriteIndex = $86
player0x = $87
NewSpriteX = $88 ; X position
player1x = $88
player2x = $89
player3x = $8A
player4x = $8B
player5x = $8C
player0y = $8D
NewSpriteY = $8E ; Y position
player1y = $8E
player2y = $8F
player3y = $90
player4y = $91
player5y = $92
NewNUSIZ = $93
_NUSIZ1 = $93
NUSIZ2 = $94
NUSIZ3 = $95
NUSIZ4 = $96
NUSIZ5 = $97
NewCOLUP1 = $98
_COLUP1 = $98
COLUP2 = $99
COLUP3 = $9A
COLUP4 = $9B
COLUP5 = $9C
SpriteGfxIndex = $9D
player0pointer = $A2
player0pointerlo = $A2
player0pointerhi = $A3
;P0Top = $A4
P0Top = temp5
P0Bottom = $A4
P1Bottom = $A5
player1pointerlo = $A6
player2pointerlo = $A7
player3pointerlo = $A8
player4pointerlo = $A9
player5pointerlo = $AA
player1pointerhi = $AB
player2pointerhi = $AC
player3pointerhi = $AD
player4pointerhi = $AE
player5pointerhi = $AF
player0height = $B0
spriteheight = $B1 ; heights of multiplexed player sprite
player1height = $B1
player2height = $B2
player3height = $B3
player4height = $B4
player5height = $B5
PF1temp1 = $B6
PF1temp2 = $B7
PF2temp1 = $B8
PF2temp2 = $B9
pfpixelheight = $BA
; playfield is now a pointer to graphics
playfield = $BB
PF1pointer = $BB
PF2pointer = $BD
statusbarlength = $BF
aux3 = $BF
lifecolor = $C0
pfscorecolor = $C0
aux4 = $C0
P1display = temp2 ; temp2 and temp3
lifepointer = $c1
lives = $c2
pfscore1 = $c1
pfscore2 = $c2
aux5 = $c1
aux6 = $c2
playfieldpos = $C3
RepoLine = temp4
scorepointers = $C4
temp1 = $CA ;used by kernel. can be used in program too, but
temp2 = $CB ;are obliterated when drawscreen is called.
temp3 = $CC
temp4 = $CD
temp5 = $CE
temp6 = $CF
temp7 = $D0 ; This is used to aid in bankswitching
score = $D1
pfheight = $D4
scorecolor = $D5 ;need to find other places for these, possibly...
rand = $D6
A = $d7
a = $d7
B = $d8
b = $d8
C = $d9
c = $d9
D = $da
d = $da
E = $db
e = $db
F = $dc
f = $dc
G = $dd
g = $dd
H = $de
h = $de
I = $df
i = $df
J = $e0
j = $e0
K = $e1
k = $e1
L = $e2
l = $e2
M = $e3
m = $e3
N = $e4
n = $e4
O = $e5
o = $e5
P = $e6
p = $e6
Q = $e7
q = $e7
R = $e8
r = $e8
S = $e9
s = $e9
T = $ea
t = $ea
U = $eb
u = $eb
V = $ec
v = $ec
W = $ed
w = $ed
X = $ee
x = $ee
Y = $ef
y = $ef
Z = $f0
z = $f0
spritesort = $f1 ; helps with flickersort
spritesort2 = $f2 ; helps with flickersort
spritesort3 = $f3
spritesort4 = $f4
spritesort5 = $f5
stack1 = $f6
stack2 = $f7
stack3 = $f8
stack4 = $f9
; the stack bytes above may be used in the kernel
; stack = F6-F7, F8-F9, FA-FB, FC-FD, FE-FF
MAC RETURN ; auto-return from either a regular or bankswitched module
ifnconst bankswitch
rts
else
jmp BS_return
endif
ENDM
;
; Inclues go below - order is crucial, since this is also the order in which
; they will appear in the generated assembly file
;
; header file
multispriteheader.asm
multisprite_kernel.asm
; standard startup routine.
startup.asm
; below are collections of subroutines and functions
; if you have any more to add, put them immediately below this line.
std_routines.asm
; The overscan routine goes below. it sets up sprites for the std_kernel.
; if you have any routines that will not run until the overscan period,
; put them immediately below this line.
; below is the generated batari Basic file
bB.asm
; score graphics.
score_graphics.asm
; below is the footer, which contains the score digits and startup vectors.
; If you want to create your own custom score digits, you may hack the file below,
; but first you should rename it to something else.
2600basicfooter.asm