I added a picture to the program in tutorial 21 and I got an error.
Quote
vars [u] 0080 0080
0000 ???? 0000 ????
RIOT [u] 0280 0280
TIA_REGISTERS_READ [u] 0000 0000
TIA_REGISTERS_WRITE [u] 0000 0000
INITIAL CODE SEGMENT 0000 ???? 0000 ????
----------------------------------------------------------------------
12 references to unknown symbols.
17 events requiring another assembler pass.
- Expression in mnemonic not resolved.
- Label defined after it has been referenced (forward reference).
Unrecoverable error(s) in pass, aborting assembly!
Complete.
0000 ???? 0000 ????
RIOT [u] 0280 0280
TIA_REGISTERS_READ [u] 0000 0000
TIA_REGISTERS_WRITE [u] 0000 0000
INITIAL CODE SEGMENT 0000 ???? 0000 ????
----------------------------------------------------------------------
12 references to unknown symbols.
17 events requiring another assembler pass.
- Expression in mnemonic not resolved.
- Label defined after it has been referenced (forward reference).
Unrecoverable error(s) in pass, aborting assembly!
Complete.
Here the code:
Quote
; '2600 for Newbies
; Session 21 - Sprites
; This kernel draws a simple box around the screen border
; Introduces sprites
processor 6502
include "vcs.h"
include "macro.h"
SpriteHeight = 8
SEG.U vars
ORG $80
SpriteXPosition ds 1
PlayerX ds 2 ; x coordinate
PS_temp ds 1
Sprite ds 2
SpriteEnd ds 1
;------------------------------------------------------------------------------
SEG code
ORG $F000
Reset
; Clear RAM and all TIA registers
ldx #0
lda #0
Clear sta 0,x
inx
bne Clear
ldx #$FF
txs
;------------------------------------------------
; Once-only initialisation...
lda #$45
sta COLUPF ; set the playfield colour
lda #$56
sta COLUP0
lda #$67
sta COLUP1
lda #%00000001
sta CTRLPF ; reflect playfield
lda #80
sta PlayerX+1
lda #60
sta SpriteEnd
lda #<Sprite0Data
sta Sprite
lda #>Sprite0Data
sta Sprite+1
;------------------------------------------------
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
sta WSYNC
; 37 scanlines of vertical blank...
ldx #0
VerticalBlank sta WSYNC
inx
cpx #37 ; Now waiting 37 lines
bne VerticalBlank
DrawField
ldx #0 ; this counts our scanline number
;line 1 - score player 0
lda #$90
sta COLUPF ; set the playfield colour
;lda #$00
;sta COLUBK ; set the background colour
lda #%11111111
sta PF0
sta PF1
sta PF2
linescr
sta WSYNC
inx
cpx #16
bne linescr
;ligne 1
lda #$2E
sta COLUPF ; set the playfield colour
lda #$00
sta COLUBK ; set the background colour
lda #%11111111
sta PF0
sta PF1
sta PF2
line1
sta WSYNC
inx
cpx #24
bne line1
;line 2a
lda #$2E
sta COLUPF ; set the playfield colour
lda #$42
sta COLUBK ; set the background colour
lda #%00011000
sta PF0
lda #%0
sta PF1
sta PF2
line2a
sta WSYNC
inx
cpx #168
bne line2a
;line 2l
lda #$2E
sta COLUPF ; set the playfield colour
lda #$00
sta COLUBK ; set the background colour
lda #%11111111
sta PF0
sta PF1
sta PF2
line2l
sta WSYNC
inx
cpx #176
bne line2l
:Last line
lda #$90
sta COLUBK ; set the background colour
lda #%0
sta PF0
sta PF1
sta PF2
LastLine
sta WSYNC
inx
cpx #192
bne LastLine
; again, we don't bother writing PF0-PF2 every scanline - they never change!
sta WSYNC
MiddleLines
TXA; transfer scanline count to A
SEC; well for this example I don't know the state
SBC SpriteEnd; so that's 96 - 96 = 0
adc #SpriteHeight ;remember the sprite is 8 lines high
bcc .skipMBDraw3 ;out of range???
tay
lda (Sprite),y ; use indirect loading here
sta GRP0
;sec ; 2 can often be guaranteed, and omitted
;tya ; 2
;sbc SpriteEnd ;3
;adc #SpriteHeight ;2
;bcs .MBDraw3 ;2(3)
;nop ;2
;nop ;2
;sec ;2
;bcs .skipMBDraw3 ;3
.MBDraw3
;tay
;lda (Sprite),Y ;5
;sta GRP0 ;3
.skipMBDraw3
sta WSYNC
;inx
dey
dex
bne MiddleLines
lda #0
sta GRP0
sta GRP1
lda #%01000010
sta VBLANK ;end of screen - enter blanking
; 30 scanlines of overscan...
ldy #0
sty PF0
sty PF1
sty PF2
Overscan sta WSYNC
iny
cpy #23
bne Overscan
inc SpriteEnd
ldx SpriteEnd
cpx #192
bcc LT192
ldx #0
stx SpriteEnd
LT192
; Now adjust the sprite position
inc PlayerX
ldx PlayerX
cpx #150
bcc LT160
ldx #0
stx PlayerX
LT160
dec PlayerX+1
ldx PlayerX+1
bne GT0
ldx #150
stx PlayerX+1
GT0
jsr PositionSprites
jmp StartOfFrame
PositionSprites
; Set the horizontal position of the two sprites, based upon their coordinates
; This uses the tricky 2600 method of positioning (RESPx, HMPx, etc)
; Algorithm invented a looong time ago by persons unknown
; Re-invented Feb2001 by yours truly, then optimised according to code by Thomas Jenztsch
sta WSYNC
sta HMCLR ; clear any previous movement
ldx #2 ; sprite index
PosSP
lda PlayerX-1,x
tay
lsr
lsr
lsr
lsr
sta PS_temp
tya
and #15
clc
adc PS_temp
ldy PS_temp
cmp #15
bcc NH
sbc #15
iny
NH
; Use remainder for fine adjustment
eor #7
asl
asl
asl
asl
sta HMP0-1,x ; fine movement
sta WSYNC
jsr Ret
bit 0 ; 15 cycles = 3 loops
Jiggle dey
bpl Jiggle
sta RESP0-1,x
dex
bne PosSP
sta WSYNC
sta HMOVE
sta WSYNC
rts
Ret
rts
Sprite0Data
.byte #%00000000
.byte #%10101010
.byte #%01010101
.byte #%10101010
.byte #%01010101
.byte #%10101010
.byte #%01010101
.byte #%00000000
;------------------------------------------------------------------------------
ORG $FFFA
InterruptVectors
.word Reset ; NMI
.word Reset ; RESET
.word Reset ; IRQ
END
; Session 21 - Sprites
; This kernel draws a simple box around the screen border
; Introduces sprites
processor 6502
include "vcs.h"
include "macro.h"
SpriteHeight = 8
SEG.U vars
ORG $80
SpriteXPosition ds 1
PlayerX ds 2 ; x coordinate
PS_temp ds 1
Sprite ds 2
SpriteEnd ds 1
;------------------------------------------------------------------------------
SEG code
ORG $F000
Reset
; Clear RAM and all TIA registers
ldx #0
lda #0
Clear sta 0,x
inx
bne Clear
ldx #$FF
txs
;------------------------------------------------
; Once-only initialisation...
lda #$45
sta COLUPF ; set the playfield colour
lda #$56
sta COLUP0
lda #$67
sta COLUP1
lda #%00000001
sta CTRLPF ; reflect playfield
lda #80
sta PlayerX+1
lda #60
sta SpriteEnd
lda #<Sprite0Data
sta Sprite
lda #>Sprite0Data
sta Sprite+1
;------------------------------------------------
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
sta WSYNC
; 37 scanlines of vertical blank...
ldx #0
VerticalBlank sta WSYNC
inx
cpx #37 ; Now waiting 37 lines
bne VerticalBlank
DrawField
ldx #0 ; this counts our scanline number
;line 1 - score player 0
lda #$90
sta COLUPF ; set the playfield colour
;lda #$00
;sta COLUBK ; set the background colour
lda #%11111111
sta PF0
sta PF1
sta PF2
linescr
sta WSYNC
inx
cpx #16
bne linescr
;ligne 1
lda #$2E
sta COLUPF ; set the playfield colour
lda #$00
sta COLUBK ; set the background colour
lda #%11111111
sta PF0
sta PF1
sta PF2
line1
sta WSYNC
inx
cpx #24
bne line1
;line 2a
lda #$2E
sta COLUPF ; set the playfield colour
lda #$42
sta COLUBK ; set the background colour
lda #%00011000
sta PF0
lda #%0
sta PF1
sta PF2
line2a
sta WSYNC
inx
cpx #168
bne line2a
;line 2l
lda #$2E
sta COLUPF ; set the playfield colour
lda #$00
sta COLUBK ; set the background colour
lda #%11111111
sta PF0
sta PF1
sta PF2
line2l
sta WSYNC
inx
cpx #176
bne line2l
:Last line
lda #$90
sta COLUBK ; set the background colour
lda #%0
sta PF0
sta PF1
sta PF2
LastLine
sta WSYNC
inx
cpx #192
bne LastLine
; again, we don't bother writing PF0-PF2 every scanline - they never change!
sta WSYNC
MiddleLines
TXA; transfer scanline count to A
SEC; well for this example I don't know the state
SBC SpriteEnd; so that's 96 - 96 = 0
adc #SpriteHeight ;remember the sprite is 8 lines high
bcc .skipMBDraw3 ;out of range???
tay
lda (Sprite),y ; use indirect loading here
sta GRP0
;sec ; 2 can often be guaranteed, and omitted
;tya ; 2
;sbc SpriteEnd ;3
;adc #SpriteHeight ;2
;bcs .MBDraw3 ;2(3)
;nop ;2
;nop ;2
;sec ;2
;bcs .skipMBDraw3 ;3
.MBDraw3
;tay
;lda (Sprite),Y ;5
;sta GRP0 ;3
.skipMBDraw3
sta WSYNC
;inx
dey
dex
bne MiddleLines
lda #0
sta GRP0
sta GRP1
lda #%01000010
sta VBLANK ;end of screen - enter blanking
; 30 scanlines of overscan...
ldy #0
sty PF0
sty PF1
sty PF2
Overscan sta WSYNC
iny
cpy #23
bne Overscan
inc SpriteEnd
ldx SpriteEnd
cpx #192
bcc LT192
ldx #0
stx SpriteEnd
LT192
; Now adjust the sprite position
inc PlayerX
ldx PlayerX
cpx #150
bcc LT160
ldx #0
stx PlayerX
LT160
dec PlayerX+1
ldx PlayerX+1
bne GT0
ldx #150
stx PlayerX+1
GT0
jsr PositionSprites
jmp StartOfFrame
PositionSprites
; Set the horizontal position of the two sprites, based upon their coordinates
; This uses the tricky 2600 method of positioning (RESPx, HMPx, etc)
; Algorithm invented a looong time ago by persons unknown
; Re-invented Feb2001 by yours truly, then optimised according to code by Thomas Jenztsch
sta WSYNC
sta HMCLR ; clear any previous movement
ldx #2 ; sprite index
PosSP
lda PlayerX-1,x
tay
lsr
lsr
lsr
lsr
sta PS_temp
tya
and #15
clc
adc PS_temp
ldy PS_temp
cmp #15
bcc NH
sbc #15
iny
NH
; Use remainder for fine adjustment
eor #7
asl
asl
asl
asl
sta HMP0-1,x ; fine movement
sta WSYNC
jsr Ret
bit 0 ; 15 cycles = 3 loops
Jiggle dey
bpl Jiggle
sta RESP0-1,x
dex
bne PosSP
sta WSYNC
sta HMOVE
sta WSYNC
rts
Ret
rts
Sprite0Data
.byte #%00000000
.byte #%10101010
.byte #%01010101
.byte #%10101010
.byte #%01010101
.byte #%10101010
.byte #%01010101
.byte #%00000000
;------------------------------------------------------------------------------
ORG $FFFA
InterruptVectors
.word Reset ; NMI
.word Reset ; RESET
.word Reset ; IRQ
END
Thanks in advance
Edited by Serguei2, Wed Jul 13, 2005 8:59 PM.













