Playing with a sprite load code, attempting text, and palette swap

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
Esns68
Posts: 31
Joined: Tue Jan 07, 2020 2:03 pm

Playing with a sprite load code, attempting text, and palette swap

Post by Esns68 » Fri Feb 05, 2021 10:46 pm

So, I'm a learning beginner, and I'm just playing around with source code that loads a sprite.
https://wiki.superfamicom.org/snes-sprites
So I was successful in getting it to load my own sprite. I was even able to change the code from doing the flashing background thing to just a black background, because I wanted my first program to be plain and simple.
And my there was my first successful SNES program! And I was very happy.

So since then I had goals to add a little more to it.
First I wanted to add some text to it.
And, I wanted to be able to do a palette swap.

I was attempted to figure out the palette swap on my own with what I knew.
My idea was to have a number, called choice,
and the user would press left or right to increase or decrease the number,
and each of those numbers would load a certain palette.

So, so far I my attempts haven't been quite successful.

So in this project I was just using the included includes, with it's own header, initializer, and LoadGraphics,
when I was just trying to load my sprite.

But since I've been trying to do the other things, I added includes from Neviksti's SNES_Starter kit, like Strings.asm and 2input.asm.

At first I was just trying to load text to it, I copied the loading text line and the text from walker.asm (Just to get sample words to work first)
After attempting this a couple times, my program work the same and displayed my sprite, but my text did not show up.

I decided to worry about later and attempt to do my palette swapping idea.
So far I only have 2 palettes.
So I did what what I did, trying to do it with branches and stuff.
After a couple a couple attempts at this, and when I tested it after each, the program displays again but flickers over and over.

Code: Select all

.INCLUDE "header.inc"
.INCLUDE "init.inc"
.INCLUDE "LoadGraphics.asm"
.INCLUDE "Strings.asm"
.INCLUDE "2input.asm"

;Definition
.DEFINE choice $01



.BANK 0 SLOT 0
.ORG 0
.SECTION "main"

main:

InitSNES

rep #$10 ; X Y 16-bit
sep #$20 ; A 8-bit



lda #%00001001
sta $2105 ; Mode 1


stz $2121
stz $2122
stz $2122

;choice
lda choice
cmp #$01
beq loadpalette1

cmp #$02
beq loadpalette2

;Pallete lables

loadpalette1:

LoadPalette emitpal0, 128, 16
jmp rest

loadpalette2:

LoadPalette emitpal1, 128, 16
jmp rest


rest:


LoadBlockToVRAM emit, $0000, $0800
LoadBlockToVRAM text, $5000, $0800

jsr SpriteInit	
	
;Emit's location
lda #(256/2 - 16)
sta $0000
lda #(224/2 - 16)
sta $0001

stz $0002

lda #%00110000 ; no flips, set priority
sta $0003

    ;lda #%11000000
    ;sta $0100
 
   
    lda #%01010100
    sta $0200
	
	;         ---12345678901234567890123456789012---
	PrintString " 'Look Ma, I can Walk!' \n"
	PrintString "   Tile pics: from Darrok \n"
	PrintString "   Walker pics: from a Demo ROM\n"
	PrintString "     - coded by: Neviksti -  "
	
jsr SetupVideo

;lda #$80
;sta $4200

continue:
JSR JoyInit		;setup joypads and enable NMI
sep #$30 ; X Y 16-bit
lda choice
tax

WAI

_up:
	lda	Joy1+1
	and	#$08
	beq	_down
	bra	_done

_down:
	lda	Joy1+1
	and	#$04
	beq	_left
	bra	_done

; left decreses
_left: 
	lda	Joy1+1
	and	#$02
	beq	_right
	dex
	bra	_done
;right increases
_right:
	lda	Joy1+1
	and	#$01
	beq	_done
	inx
	bra _done


	
	_done:
	txa
	
	cmp #$00
	beq if0
	
	cmp #$03
	beq if3
	jmp reallydone
	
	if0:
	lda #$02
	jmp reallydone
	
	if3:
	lda #$01
	jmp reallydone
	
	reallydone:
	
	sta choice
	jmp main
;============================================================================
SpriteInit:
	php	

	rep	#$30	;16bit mem/A, 16 bit X/Y
	
	ldx #$0000
    lda #$0001
_setoffscr:
    sta $0000,X
    inx
    inx
    inx
    inx
    cpx #$0200
    bne _setoffscr
;==================
	ldx #$0000
	lda #$5555
_clr:
	sta $0200, X		;initialize all sprites to be off the screen
	inx
	inx
	cpx #$0020
	bne _clr
;==================

	plp
	rts
;============================================================================
;============================================================================
; SetupVideo -- Sets up the video mode and tile-related registers
;----------------------------------------------------------------------------
; In: None
;----------------------------------------------------------------------------
; Out: None
;----------------------------------------------------------------------------
SetupVideo:
    php
    
    rep #$10
    sep #$20
    
    stz $2102
    stz $2103
    
    ;*********transfer sprite data

	stz $2102		; set OAM address to 0
	stz $2103

	LDY #$0400
	STY $4300		; CPU -> PPU, auto increment, write 1 reg, $2104 (OAM Write)
	stz $4302
	stz $4303		; source offset
	LDY #$0220
	STY $4305		; number of bytes to transfer
	LDA #$7E
	STA $4304		; bank address = $7E  (work RAM)
	LDA #$01
	STA $420B		;start DMA transfer
	
	lda #%10100000
    sta $2101

    lda #%00010000            ; Enable BG1
    sta $212C
    
    lda #$0F
    sta $2100           ; Turn on screen, full Brightness

    plp
    rts



;============================================================================
VBlank:
    rep #$30        ; A/mem=16 bits, X/Y=16 bits (to push all 16 bits)
    phb
	pha
	phx
	phy
	phd

    sep #$20        ; A/mem=8 bit    
    
    



    lda $4210       ; Clear NMI flag
    rep #$30        ; A/Mem=16 bits, X/Y=16 bits 
    
    PLD 
	PLY 
	PLX 
	PLA 
	PLB 

    sep #$20
    RTI

;============================================================================

.ends

;-----Graphics data------

.BANK 1 SLOT 0
.ORG 0
.SECTION "graphics"

emit:
.INCBIN "emit.pic"

emitpal0:
.INCBIN "emit.clr"

emitpal1:
.INCBIN "emitred.clr"

text:
.INCBIN "ascii.pic"
	

.ENDS
The first thing thing I'm curious about is the text,
I was wondering if it was because Nev's Strings.asm conflicts with this other programmer's coding of his source code and included sources, like his own LoadGraphics.
When I did the loadgraphics text line, I just copy and pasted from Walker.asm so maybe it just has to do with how it's loaded at those addresses here?
Otherwise, maybe how I written things interferes with Vblank and stuff, which I'm still learning about.

For the input, again I copied and pasted from walker, but I got rid of the frame loading stuff.

And I'm wondering the way I tried to write to accomplish this paletteswap idea is functional at all.

I'm still learning about vblank and all that, but I just wondered about what things I'm doing wrong, so I can understand more about how all these things work.
Am I just loading and setting things in the wrong order? Am I messing up on loading the graphics?
Like at

Code: Select all

jsr SetupVideo

;lda #$80
;sta $4200

continue:
JSR JoyInit		;setup joypads and enable NMI
I remember commenting that out becuase I think that enables NMI, and I wasn't sure I should have that if that joypad thing says it enables NMI.
That brings up the point, at what points should I have enabled NMI?

Again, a lot of this because I still don't understand everything and am still learning how all this Vblank and stuff works, so I'm just looking for a little guidance on working with this.

Thank you for your time!

Oziphantom
Posts: 1080
Joined: Tue Feb 07, 2017 2:03 am

Re: Playing with a sprite load code, attempting text, and palette swap

Post by Oziphantom » Sat Feb 06, 2021 3:39 am

So the SNES.

There is NO operating system there is no text or font or printf. There is no TTY or anything. So you can't just expect it to work and be set up and work with everything. There is no dynamic memory allocation.

So in order for the text to work as that example has it.
The FONT tiles must be placed in VRAM exactly where it expects and can not have anything else loaded over the top of them.
the Screen mode must be exactly as it wants and the correct screen layer must be enabled.
the screen map must be set to exactly where it needs it to be
the screen map size must be correct
the pallete must have the right values in the right pallete slots that matches the font data and the map data.

and you must have done all of your uploads to VRAM during VBlank. In that you must complete during VBlank, if you start at the end of VBlank they it will work for a bit and then you will get garbage. How much you can roughly transfer during VBlank depends upon if you are in PAL or NTSC mode.

If any one of those things is off by 1 bit, it will fail.

When do you enable NMI? Whenever you have set up the NMI handler and it is ready to start running. There is no rule, it is when your code is ready.

Note the NMI is not VBlank, and enabling NMI does not enable or disable the VBlank. You are only enabling it to be triggered when VBlank starts or not be triggered.

use MESEN and look at VRAM to see what makes it to VRAM and where.

User avatar
dougeff
Posts: 2823
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Playing with a sprite load code, attempting text, and palette swap

Post by dougeff » Sat Feb 06, 2021 6:18 am

sep #$30 ; X Y 16-bit
this comment is wrong, should say XY 8 bit
which is what you want, since the code below uses 8 bit values

jmp main
not correct. I think you meant jmp continue

but JSR JoyInit should probably go above continue: since it should only be done once... and there's probably a difference subroutine to read the joypads. (?) jsr Joypad in Bazz's tutorial... which should be run once a frame.
nesdoug.com -- blog/tutorial on programming for the NES

Esns68
Posts: 31
Joined: Tue Jan 07, 2020 2:03 pm

Re: Playing with a sprite load code, attempting text, and palette swap

Post by Esns68 » Sun Feb 07, 2021 4:56 am

About the text, I copy and pasted that "loadtovram text" line there exactly as it was in the other program,
for those kinds of reasons, I assumed maybe it expected to loaded at that exact address. Otherwise, I'm not still
not sure on getting that text to work here.

Also, I'm writing NTSC.

I played with the code some more. Honestly, I don't even know why I put that continue again.
But my I had it set to jump to main so that the choice number would reach load palette section.
I thought it might as well just start the program again, but just load the palette with the current number
since the the overall program would be the same.

I tried putting things around differently like you suggested, at this point. I'm just getting a black screen.

Code: Select all

.INCLUDE "header.inc"
.INCLUDE "init.inc"
.INCLUDE "LoadGraphics.asm"
.INCLUDE "Strings.asm"
.INCLUDE "2input.asm"

;Definition
.DEFINE choice $01



.BANK 0 SLOT 0
.ORG 0
.SECTION "main"

main:

InitSNES

rep #$10 ; X Y 16-bit
sep #$20 ; A 8-bit



lda #%00001001
sta $2105 ; Mode 1


stz $2121
stz $2122
stz $2122
lda #$01
sta choice
continue:

;choice
lda choice
cmp #$01
beq loadpalette1

cmp #$02
beq loadpalette2

;Pallete lables

loadpalette1:

LoadPalette emitpal0, 128, 16
jmp rest

loadpalette2:

LoadPalette emitpal1, 128, 16
jmp rest


rest:


LoadBlockToVRAM emit, $0000, $0800
LoadBlockToVRAM text, $5000, $0800

jsr SpriteInit	
	
;Emit's location
lda #(256/2 - 16)
sta $0000
lda #(224/2 - 16)
sta $0001

stz $0002

lda #%00110000 ; no flips, set priority
sta $0003

    ;lda #%11000000
    ;sta $0100
 
   
    lda #%01010100
    sta $0200
	
	;         ---12345678901234567890123456789012---
	PrintString " 'Look Ma, I can Walk!' \n"
	PrintString "   Tile pics: from Darrok \n"
	PrintString "   Walker pics: from a Demo ROM\n"
	PrintString "     - coded by: Neviksti -  "
	
jsr SetupVideo

;lda #$80
;sta $4200

JSR JoyInit		;setup joypads and enable NMI

sep #$30 ; X Y 8-bit
lda choice
tax

WAI

_up:
	lda	Joy1+1
	and	#$08
	beq	_down
	bra	_done

_down:
	lda	Joy1+1
	and	#$04
	beq	_left
	bra	_done

_left:
	lda	Joy1+1
	and	#$02
	beq	_right
	dex
	bra	_done

_right:
	lda	Joy1+1
	and	#$01
	beq	_done
	inx
	bra _done


	
	_done:
	txa
	
	cmp #$00
	beq if0
	
	cmp #$03
	beq if3
	jmp reallydone
	
	if0:
	lda #$02
	jmp reallydone
	
	if3:
	lda #$01
	jmp reallydone
	
	reallydone:
	
	sta choice
	jmp main
;============================================================================
SpriteInit:
	php	

	rep	#$30	;16bit mem/A, 16 bit X/Y
	
	ldx #$0000
    lda #$0001
_setoffscr:
    sta $0000,X
    inx
    inx
    inx
    inx
    cpx #$0200
    bne _setoffscr
;==================
	ldx #$0000
	lda #$5555
_clr:
	sta $0200, X		;initialize all sprites to be off the screen
	inx
	inx
	cpx #$0020
	bne _clr
;==================

	plp
	rts
;============================================================================
;============================================================================
; SetupVideo -- Sets up the video mode and tile-related registers
;----------------------------------------------------------------------------
; In: None
;----------------------------------------------------------------------------
; Out: None
;----------------------------------------------------------------------------
SetupVideo:
    php
    
    rep #$10
    sep #$20
    
    stz $2102
    stz $2103
    
    ;*********transfer sprite data

	stz $2102		; set OAM address to 0
	stz $2103

	LDY #$0400
	STY $4300		; CPU -> PPU, auto increment, write 1 reg, $2104 (OAM Write)
	stz $4302
	stz $4303		; source offset
	LDY #$0220
	STY $4305		; number of bytes to transfer
	LDA #$7E
	STA $4304		; bank address = $7E  (work RAM)
	LDA #$01
	STA $420B		;start DMA transfer
	
	lda #%10100000
    sta $2101

    lda #%00010000            ; Enable BG1
    sta $212C
    
    lda #$0F
    sta $2100           ; Turn on screen, full Brightness

    plp
    rts



;============================================================================
VBlank:
    rep #$30        ; A/mem=16 bits, X/Y=16 bits (to push all 16 bits)
    phb
	pha
	phx
	phy
	phd

    sep #$20        ; A/mem=8 bit    
    
    



    lda $4210       ; Clear NMI flag
    rep #$30        ; A/Mem=16 bits, X/Y=16 bits 
    
    PLD 
	PLY 
	PLX 
	PLA 
	PLB 

    sep #$20
    RTI

;============================================================================

.ends

;-----Graphics data------

.BANK 1 SLOT 0
.ORG 0
.SECTION "graphics"

emit:
.INCBIN "emit.pic"

emitpal0:
.INCBIN "emit.clr"

emitpal1:
.INCBIN "emitred.clr"

text:
.INCBIN "ascii.pic"
	

.ENDS
I just wondered if I'm doing I'm doing the branching wrong. Did I at least get the idea right?
Again I still don't know what I'm doing in assembly but I tried with what I knew so far.
What I was trying to do was:
Have a program where the user would press left or right to toggle the sprite's color.
I was gonna make a variable called choice.
I plan to have more when I get it to work, but right now I only have 2 palettes.
Right would increase the number in choice, and left would decrease it.
Number 1 would load the main palette, and number 2 would load the other palette.
I also tried making code to reset to 1 if the number was increased to 3,
and set to 2 if the number was decreased to 0.

Also were you saying I should ditch that joypad include code for Bazz's? Now that I looked I think Bazz is the person who did this sprite.asm code.

Do you have any advice on adapting Nev's Strings.asm to this source code? I looked at it myself but it was beyond my comprehension right now.


Also there was just one thing I was still just curious about.

Code: Select all


_up:
	lda	Joy1+1
	and	#$08
	beq	_down
	bra	_done

What do those parts in all of those direction labels? (Again, this was from walker.asm)
I think there supposed to check if there that direction, but how does that do that?
I've heard a little about that AND instruction, but I'm still learning what does, I had a little hard time understanding that one.
What is it doing in this case, to help with whatever is going on there?

Oziphantom
Posts: 1080
Joined: Tue Feb 07, 2017 2:03 am

Re: Playing with a sprite load code, attempting text, and palette swap

Post by Oziphantom » Sun Feb 07, 2021 6:37 am

Esns68 wrote:
Sun Feb 07, 2021 4:56 am
About the text, I copy and pasted that "loadtovram text" line there exactly as it was in the other program,
for those kinds of reasons, I assumed maybe it expected to loaded at that exact address. Otherwise, I'm not still
not sure on getting that text to work here.
Yes that is important, however it also important you then don't do anything else that undoes anything it has done. Like say upload sprite data over the top of the font. Or Modify the Screen mode it set up, or disabled showing the layer that it has when you turn on sprites because you don't understand how AND, OR work and you don't understand how the text function actually works, what resources on the SNES it uses and how it configs the SNES. And you need to understand all of those things first. The SNES is not a machine you "get it working" and then "figure out how it worked". the SNES is "I fully 100% understand 6502 and 65816 and how the machine operates" and then "figure out how to get this working". Case in point the programmer of this https://www.youtube.com/watch?v=YEi3bv2duXw which is an Atari Lynx demo which uses a 65C02S, i.e somebody who can write 3D maths in 6502 knows every instruction, every detail, understand tiles, VRAM, sprites, registers to a very deep level, needed a lot of help with the BASICs of the SNES and help debugging why a screen didn't show or why a sprite was in the wrong position etc
Also, I'm writing NTSC.
try switching to PAL in the emulator and if that gets your further, then you know you are running out of VBLank. You will get about 4K transferred during VBlank on NTSC.
I played with the code some more. Honestly, I don't even know why I put that continue again.
But my I had it set to jump to main so that the choice number would reach load palette section.
I thought it might as well just start the program again, but just load the palette with the current number
since the the overall program would be the same.

I tried putting things around differently like you suggested, at this point. I'm just getting a black screen.

Code: Select all

.INCLUDE "header.inc"
.INCLUDE "init.inc"
.INCLUDE "LoadGraphics.asm"
.INCLUDE "Strings.asm"
.INCLUDE "2input.asm"

;Definition
.DEFINE choice $01



.BANK 0 SLOT 0
.ORG 0
.SECTION "main"

main:

InitSNES

rep #$10 ; X Y 16-bit
sep #$20 ; A 8-bit



lda #%00001001
sta $2105 ; Mode 1


stz $2121
stz $2122
stz $2122
lda #$01
sta choice
continue:

;choice
lda choice
cmp #$01
beq loadpalette1

cmp #$02
beq loadpalette2

;Pallete lables

loadpalette1:

LoadPalette emitpal0, 128, 16
jmp rest

loadpalette2:

LoadPalette emitpal1, 128, 16
jmp rest


rest:


LoadBlockToVRAM emit, $0000, $0800 ; do this once and only once don't do it each loop
LoadBlockToVRAM text, $5000, $0800 ; this is 4K worth of data, plus other logic is going to push VBlank time very hard

jsr SpriteInit	 ; do this once only as well, it will eat a chunk of VBlank time and doesn't need to be done in vblank
	
;Emit's location
lda #(256/2 - 16)
sta $0000
lda #(224/2 - 16)
sta $0001

stz $0002

lda #%00110000 ; no flips, set priority
sta $0003

    ;lda #%11000000
    ;sta $0100
 
   
    lda #%01010100
    sta $0200
	
	;         ---12345678901234567890123456789012---
	PrintString " 'Look Ma, I can Walk!' \n"
	PrintString "   Tile pics: from Darrok \n"
	PrintString "   Walker pics: from a Demo ROM\n"
	PrintString "     - coded by: Neviksti -  "
	
jsr SetupVideo

;lda #$80
;sta $4200

JSR JoyInit		;setup joypads and enable NMI

sep #$30 ; X Y 8-bit
lda choice
tax

WAI

_up:
	lda	Joy1+1
	and	#$08
	beq	_down ; buttons are ACTIVE LOW, so this jumps if the button is pressed
	bra	_done ; this stops checking anything and goes to the end

_down:
	lda	Joy1+1
	and	#$04
	beq	_left ;yeah
	bra	_done

_left:
	lda	Joy1+1
	and	#$02
	beq	_right ; same
	dex
	bra	_done

_right:
	lda	Joy1+1
	and	#$01
	beq	_done ; and again
	inx
	bra _done


	
	_done:
	txa
	
	cmp #$00
	beq if0
	
	cmp #$03
	beq if3
	jmp reallydone
	
	if0:
	lda #$02
	jmp reallydone
	
	if3:
	lda #$01
	jmp reallydone
	
	reallydone:
	
	sta choice
	jmp main ; WHY DO YOU REINIT THE WHOLE SNES FROM THE TOP ??? the will ruin everything and take frames
;============================================================================
SpriteInit:
	php	

	rep	#$30	;16bit mem/A, 16 bit X/Y
	
	ldx #$0000
    lda #$0001
_setoffscr:
    sta $0000,X
    inx
    inx
    inx
    inx
    cpx #$0200
    bne _setoffscr
;==================
	ldx #$0000
	lda #$5555
_clr:
	sta $0200, X		;initialize all sprites to be off the screen
	inx
	inx
	cpx #$0020
	bne _clr
;==================

	plp
	rts
;============================================================================
;============================================================================
; SetupVideo -- Sets up the video mode and tile-related registers
;----------------------------------------------------------------------------
; In: None
;----------------------------------------------------------------------------
; Out: None
;----------------------------------------------------------------------------
SetupVideo:
    php
    
    rep #$10
    sep #$20
    
    stz $2102
    stz $2103
    
    ;*********transfer sprite data

	stz $2102		; set OAM address to 0
	stz $2103

	LDY #$0400
	STY $4300		; CPU -> PPU, auto increment, write 1 reg, $2104 (OAM Write)
	stz $4302
	stz $4303		; source offset
	LDY #$0220
	STY $4305		; number of bytes to transfer
	LDA #$7E
	STA $4304		; bank address = $7E  (work RAM)
	LDA #$01
	STA $420B		;start DMA transfer
	
	lda #%10100000
    sta $2101

    lda #%00010000            ; Enable BG1
    sta $212C
    
    lda #$0F
    sta $2100           ; Turn on screen, full Brightness

    plp
    rts



;============================================================================
VBlank:
    rep #$30        ; A/mem=16 bits, X/Y=16 bits (to push all 16 bits)
    phb
	pha
	phx
	phy
	phd

    sep #$20        ; A/mem=8 bit    
    
    



    lda $4210       ; Clear NMI flag
    rep #$30        ; A/Mem=16 bits, X/Y=16 bits 
    
    PLD 
	PLY 
	PLX 
	PLA 
	PLB 

    sep #$20
    RTI

;============================================================================

.ends

;-----Graphics data------

.BANK 1 SLOT 0
.ORG 0
.SECTION "graphics"

emit:
.INCBIN "emit.pic"

emitpal0:
.INCBIN "emit.clr"

emitpal1:
.INCBIN "emitred.clr"

text:
.INCBIN "ascii.pic"
	

.ENDS
see my comments above, the better way to write this is
So here is a more correct version, without having the assets its impossible to assemble and this is off the top of my head

Code: Select all

.INCLUDE "header.inc"
.INCLUDE "init.inc"
.INCLUDE "LoadGraphics.asm"
.INCLUDE "Strings.asm"
.INCLUDE "2input.asm"

;Definition
.DEFINE choice $01



.BANK 0 SLOT 0
.ORG 0
.SECTION "main"

main:

InitSNES

rep #$10 ; X Y 16-bit
sep #$20 ; A 8-bit



lda #%00001001
sta $2105 ; Mode 1


stz $2121
stz $2122
stz $2122
lda #$01
sta choice
continue:



rest:


LoadBlockToVRAM emit, $0000, $0800 ; do this once and only once don't do it each loop
LoadBlockToVRAM text, $5000, $0800 ; this is 4K worth of data, plus other logic is going to push VBlank time very hard

jsr SpriteInit	 ; do this once only as well, it will eat a chunk of VBlank time and doesn't need to be done in vblank
	
;Emit's location
lda #(256/2 - 16)
sta $0000
lda #(224/2 - 16)
sta $0001

stz $0002

lda #%00110000 ; no flips, set priority
sta $0003

    ;lda #%11000000
    ;sta $0100
 
   
    lda #%01010100
    sta $0200
	
	;         ---12345678901234567890123456789012---
	PrintString " 'Look Ma, I can Walk!' \n"
	PrintString "   Tile pics: from Darrok \n"
	PrintString "   Walker pics: from a Demo ROM\n"
	PrintString "     - coded by: Neviksti -  "
	
jsr SetupVideo

;lda #$80
;sta $4200

JSR JoyInit		;setup joypads and enable NMI

mainLoop
rep #$10 ; X Y 16-bit
sep #$20 ; A 8-bit

;choice
uploadPal:
lda choice
cmp #$01
beq loadpalette1

cmp #$02
beq loadpalette2

;Pallete lables

loadpalette1:

LoadPalette emitpal0, 128, 16
bra waitNextFrame

loadpalette2:

LoadPalette emitpal1, 128, 16

waitNextFrame
WAI

_up:
	lda	Joy1+1
	and	#$08
	bne	_down
	bra	waitNextFrame

_down:
	lda	Joy1+1
	and	#$04
	bne	_left
	bra	waitNextFrame

_left:
	lda	Joy1+1
	and	#$02
	bne	_right
	dec     choice
	bra	_done

_right:
	lda	Joy1+1
	and	#$01
	bne	waitNextFrame
	inc     choice

_done:
        lda choice
        and #1        ; this will limit to 0, 1
        sta choice
	jmp uploadPal
;============================================================================
SpriteInit:
	php	

	rep	#$30	;16bit mem/A, 16 bit X/Y
	
	ldx #$0000
    lda #$0001
_setoffscr:
    sta $0000,X
    inx
    inx
    inx
    inx
    cpx #$0200
    bne _setoffscr
;==================
	ldx #$0000
	lda #$5555
_clr:
	sta $0200, X		;initialize all sprites to be off the screen
	inx
	inx
	cpx #$0020
	bne _clr
;==================

	plp
	rts
;============================================================================
;============================================================================
; SetupVideo -- Sets up the video mode and tile-related registers
;----------------------------------------------------------------------------
; In: None
;----------------------------------------------------------------------------
; Out: None
;----------------------------------------------------------------------------
SetupVideo:
    php
    
    rep #$10
    sep #$20
    
    stz $2102
    stz $2103
    
    ;*********transfer sprite data

	stz $2102		; set OAM address to 0
	stz $2103

	LDY #$0400
	STY $4300		; CPU -> PPU, auto increment, write 1 reg, $2104 (OAM Write)
	stz $4302
	stz $4303		; source offset
	LDY #$0220
	STY $4305		; number of bytes to transfer
	LDA #$7E
	STA $4304		; bank address = $7E  (work RAM)
	LDA #$01
	STA $420B		;start DMA transfer
	
	lda #%10100000
    sta $2101

    lda #%00010000            ; Enable BG1
    sta $212C
    
    lda #$0F
    sta $2100           ; Turn on screen, full Brightness

    plp
    rts



;============================================================================
VBlank:
    rep #$30        ; A/mem=16 bits, X/Y=16 bits (to push all 16 bits)
    phb
	pha
	phx
	phy
	phd

    sep #$20        ; A/mem=8 bit    
    
    



    lda $4210       ; Clear NMI flag
    rep #$30        ; A/Mem=16 bits, X/Y=16 bits 
    
    PLD 
	PLY 
	PLX 
	PLA 
	PLB 

    sep #$20
    RTI

;============================================================================

.ends

;-----Graphics data------

.BANK 1 SLOT 0
.ORG 0
.SECTION "graphics"

emit:
.INCBIN "emit.pic"

emitpal0:
.INCBIN "emit.clr"

emitpal1:
.INCBIN "emitred.clr"

text:
.INCBIN "ascii.pic"
	

.ENDS
I just wondered if I'm doing I'm doing the branching wrong. Did I at least get the idea right?
Again I still don't know what I'm doing in assembly but I tried with what I knew so far.
What I was trying to do was:
Have a program where the user would press left or right to toggle the sprite's color.
I was gonna make a variable called choice.
I plan to have more when I get it to work, but right now I only have 2 palettes.
Right would increase the number in choice, and left would decrease it.
Number 1 would load the main palette, and number 2 would load the other palette.
I also tried making code to reset to 1 if the number was increased to 3,
and set to 2 if the number was decreased to 0.

Also were you saying I should ditch that joypad include code for Bazz's? Now that I looked I think Bazz is the person who did this sprite.asm code.

Do you have any advice on adapting Nev's Strings.asm to this source code? I looked at it myself but it was beyond my comprehension right now.
Advice - stop trying to get "the thing working" and "understand how 6502 works completely, read a book cover to cover until you can understand what the code you are trying to use does work.
Also there was just one thing I was still just curious about.

Code: Select all


_up:
	lda	Joy1+1 ; read upper 8 bits of the joypad register to get the state
	and	#$08	   ; mask the 4th bit or bit3 of the joypad register
	beq	_down  ; if the bit is 0 then branch to _down. This is not what you actually want to do but it is what it does
	bra	_done  ; the bit was 1 so "branch always" aka "relative jump" to _done

What do those parts in all of those direction labels? (Again, this was from walker.asm)
I think there supposed to check if there that direction, but how does that do that?
see my comments unlined above
I've heard a little about that AND instruction, but I'm still learning what does, I had a little hard time understanding that one.
What is it doing in this case, to help with whatever is going on there?
It performs a binary AND as defined by the AND in Boolean Logic, see the wikipedia page or Chapter 1 of any 6502 book for explanation of logic gates/boolean logic. You really really need to understand boolean logic before you can write any code.

User avatar
dougeff
Posts: 2823
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Playing with a sprite load code, attempting text, and palette swap

Post by dougeff » Sun Feb 07, 2021 10:38 am

lda #%00010000 ;probably wrong
sta $210c

your comment says "enable bg1" but you are only turning on sprites here. Bg1 is this bit...

00000001

BG1 and sprites would be

00010001

and I see you copying "text" to PPU $5000, which I assume are tiles. You have to tell the PPU where the BG1 tiles are, with register 210b and where the BG1 tilemap is with register 2107.

LDA #5
STA $210b
would tell it BG1 tiles are at $5000

It's not clear to me where you want the tilemap to be.

is PrintString some kind of macro? I'm not familiar with that code.

You also need to put some palette colors for the BG. I think they (BG palette colors) are all zero (=black).
nesdoug.com -- blog/tutorial on programming for the NES

Pokun
Posts: 1758
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Playing with a sprite load code, attempting text, and palette swap

Post by Pokun » Sun Feb 07, 2021 3:44 pm

I also think modifying an existing program sounds like a very hard way to learn as there are so many things you can break. In general, you should only modify one "thing" in a program before testing. If you modify more than one thing, you don't know which thing it was that broke it.

Code: Select all

_up:
	lda	Joy1+1
	and	#$08
	beq	_down
	bra	_done
This is part of the input handler. The code that performs actions based on player input. Joy1+1 is most likely the RAM address containing button states and it performs an AND operation on it to check if the bit for the UP button is set (which means the player is pressing UP on the d-pad). AND is useful for testing bits like this.

Post Reply