Thanks, but it still doesn't quite work. If you hold the fire button down and move the player towards the left after you reach the middle left you will notice missile 0 will "cave in" into player 0's sprite and if you continue moving left the missile will be almost completely merged with player 0's sprite and stops working altogether. If you move towards the right, everything works as normal. Any ideas?
; First we have to tell DASM that we're
; coding to the 6502:
processor 6502
; Then we have to include the "vcs.h" file
; that includes all the "convenience names"
; for all the special atari memory locations...
include "vcs.h"
include "macro.h"
;**************************************************************************
SEG.U vars; tells dasm that the proceding instructions are variable declarations
ORG $80; tells dasm to start placing our variables in memory location 0080
player0x = $80; player0's x position
player0y = $81; player0's y position
visibleplayer0line = $82; current visible line for player 0
player0buffer = $83; player buffer for holding the line to draw for the player graphic
missile0x = $84; missile 0's x position
missile0y = $85; missile 0's y position
visiblemissile0line = $86; line where missile is drawn
lives = $87; player lives
score = $88; game score
SEG code
; tell DASM where in the memory to place
; all the code that follows...$F000 is the preferred
; spot where it goes to make an atari program
ORG $F000
; we'll call the start of our program "Start".
Start
SEI; Disable Any Interrupts
CLD ; Clear BCD math bit.
LDX #$FF; put X to the top...
TXS; ...and use it reset the stack pointer
; Clear RAM and all TIA registers
lda #0;Put Zero into A, X is at $FF
Clear sta 0,x;Now, this doesn't mean what you think...
dex;decrement X (decrease X by one)
bne Clear;if the last command resulted in something
;that's "N"ot "Equal" to Zero, branch back
;to "Clear"
;---------------------
; One Time Initiations
lda #$FA
sta COLUBK; set the background color to sandy brown
lda #$04
sta COLUP0; set the player color to silver
lda #$B8
sta COLUPF; set the playfield color to ooze green
;---------------------
; Start New Game
StartNewGame lda #105
sta player0x; player0's initial x position
lda #40
sta player0y; player0's initial y position
lda #0
sta missile0x; missile 0's initial x position
lda #0
sta missile0y; missile 0's initial y position
lda #3
sta lives; start the player with 3 lives
lda #0
sta score; set high bit of score inital value to 0
lda #0
sta score+1; set nibble bit of score inital value to 0
lda #0
sta score+2; low bit of score inital value to 0
GameLoop
;*********************** VERTICAL SYNC HANDLER
lda #2
sta VSYNC; Sync it up you damn dirty television!
; and that vsync on needs to be held for three scanlines...
; count with me here,
sta WSYNC; one... (our program waited for the first scanline to finish...)
sta WSYNC; two...
sta WSYNC; three...
lda #43;load 43 (decimal) in the accumulator
sta TIM64T;and store that in the timer
lda #0; Zero out the VSYNC
sta VSYNC; cause that time is over
;*********************** Joystick Input
; Here we check for left and right
; joystick input
lda #%01000000; a 0 in bit D6 means the joystick was pushed left
bit SWCHA; was the joystick moved left?
bne SkipPlayer0MoveLeft; if bit D6 isn't equal to 0 then jump to SkipPlayer0MoveLeft
dec player0x; otherwise the player moved the joystick left so deincrement the players position by one
SkipPlayer0MoveLeft
lda #%10000000; a 0 in bit D7 means the joystick was pushed right
bit SWCHA; was the joystick moved right?
bne SkipPlayer0MoveRight;if bit D6 isn't equal to 0 then jump to SkipPlayer0MoveRight
inc player0x;otherwise the player moved the joystick right so increment the players position by one
SkipPlayer0MoveRight
lda player0x; load the players position into the accumulator
ldx #0; set the sprite to be positioned as player 0
jsr PositionSprite; jump to our Position Sprite Subroutine to position player 0
sta WSYNC; wait for sync
lda #0; zero out the buffer
sta player0buffer; just in case
lda INPT4; read button input
bmi ButtonNotPressed; skip if button not pressed
lda player0x; load player 0's x position
sta missile0x; and set it to the missile 0's x position
lda #4; set the acumulator to 4
clc; clear carry status
adc missile0x; add 4 to missile 0's x position so it's centered at player 0
sta missile0x; and set it to missile 0's x position
lda player0y; load player 0's y position
sta missile0y; and set it to missile 0's y position
lda #8; set the acumulator to 8
clc; clear carry status
adc missile0y; add 8 to missile 0's y position so it's above player 0
sta missile0y; and set it to missile 0's y position
lda missile0x; load missile 0's x position into the accumulator
ldx #2; set the sprite to be positioned to missile 0
jsr PositionSprite; jump to our Position Sprite Subroutine to position missile 0
ButtonNotPressed
;*********************** VERTICAL BLANK WAIT-ER
WaitForVblankEnd
lda INTIM;load timer...
BNE WaitForVblankEnd;killing time if the timer's not yet zero
ldy #191;Y is going to hold how many lines we have to do
;...we're going to count scanlines here. theoretically
; since this example is ass simple, we could just repeat
; the timer trick, but often its important to know
; just what scan line we're at.
sta WSYNC;We do a WSYNC just before that so we don't turn on
sta VBLANK;End the VBLANK period with the zero
;*********************** Scan line Loop
ScanLoop
sta WSYNC;Wait for the previous line to finish
lda player0buffer;buffer was set during last scanline
sta GRP0;put it as graphics now
cpy player0y; compare the player's y position
bne SkipActivatePlayer0; if it isn't 0 then jump to SkipActivePlayer0
lda #5; otherwise load our accumulatior with the number of lines to draw
sta visibleplayer0line; and store it
SkipActivatePlayer0
;set player buffer to all zeros for this line, and then see if
;we need to load it with graphic data
lda #0
sta player0buffer;set buffer, not GRP0
;if the VisiblePlayerLine is non zero,
;we're drawing it next line
ldx visibleplayer0line;check the visible player line...
beq FinishPlayer;skip the drawing if its zero...
lda player0-1,X;otherwise, load the correct line from player0
;section below... it's off by 1 though, since at zero
;we stop drawing
sta player0buffer;put that line as player graphic for the next line
dec visibleplayer0line;and decrement the line count
FinishPlayer
; here the idea is that visiblemissile0line
; is zero if the line isn't being drawn now,
; otherwise it's however many lines we have to go
CheckActivateMissile
cpy missile0y; is missile 0's y position the same as the current scanline?
bne SkipActivateMissile; if it isn't then don't set missle 0's visible lines
lda #8; otherwise set the missiles visible lines to 8
sta visiblemissile0line; and store it in the visiblemissileline
SkipActivateMissile
;turn missile off then see if it's turned on
lda #0
sta ENAM0; disable the missile
;if the visiblemissile0line is non zero,
;we're drawing it
lda visiblemissile0line; if the visiblemissle line is zero
beq FinishMissile; don't draw the missile
lda #2; otherwise set the accumulator to 2
sta ENAM0; and draw the missile
dec visiblemissile0line; and decrement the visiblemissileline by 1
inc missile0y; increment missle 0's y position by 1
FinishMissile
dey;subtract one off the line counter thingy
bne ScanLoop;and repeat if we're not finished with all the scanlines.
lda #2;#2 for the VBLANK...
sta WSYNC;Finish this final scanline.
sta VBLANK; Make TIA output invisible for the overscan,
; (and keep it that way for the vsync and vblank)
;***************************** OVERSCAN CALCULATIONS
;I'm just gonna count off the 30 lines of the overscan.
;You could do more program code if you wanted to.
ldx #30;store 30
OverScanWait
sta WSYNC
dex
bne OverScanWait
jmp GameLoop;Continue this loop forver! Back to the code for the vsync etc
PositionSprite
sta HMCLR
sec
sta WSYNC
PositionSpriteLoop
sbc #15
bcs PositionSpriteLoop
eor #7
asl
asl
asl
asl
sta.wx HMP0,X
sta RESP0,X
sta WSYNC
sta HMOVE
rts
; here's the actual player0 graphic
player0
.byte #%00011000
.byte #%00111100
.byte #%11111111
.byte #%00111100
.byte #%00011000
update_low_score_digits
sed; set decimal mode
clc; clear carry status
adc score; add accumulator to score's low digits w/carry.
sta score; store the updated low digits.
;NOTE: Here's where a triple-NOP comes into play. We need
;a seperate entrypoint to this subroutine for cases where the
;low digits are ignored (like adding 100, for example). But
;carry status and BCD mode need to have been setup. So,
;place the triple-NOP opcode here to skip over them...
;with A reset at zero so that only carry affects the score:
lda #0; reset the accumulator...
.byte $0C; ...and skip over the next 2 bytes
update_middle_score_digits
sed; set decimal mode
clc; clear carry status
adc score+1; add accumulator to score's middle digits w/carry.
sta score+1; store the updated middle digits
;Here we do the same thing (in case the game needs to add 10,000...
;or 100,000 increments to a score (ignoring all the lower ones)
;Again, A is reset at zero so that only carry affects the score:
lda #0; reset the accumulator...
.byte $0C; ...and skip over the next 2 bytes
update_high_score_digits
sed; set decimal mode
clc; clear carry status
adc score+1; add accumulator to score's high digits w/carry.
sta score+2; store the last 2 digits
;With the score updated, clear BCD mode and exit via RTS:
cld; clear decimal mode
rts; and return to the program line that called this routine.
;*************************************************************************
; Interrupt Vectors
ORG $FFFA
InterruptVectors
.word Start ; NMI
.word Start ; RESET
.word Start ; IRQ
END
Sincerely,
Primordial Ooze
Edited by Primordial Ooze, Sun Feb 22, 2009 8:09 PM.