better tuned sprite overlay for the title screen and more

FrankenGraphics

New member
why: i wasn't too happy with repeating two macros for each sprite as it takes up a *lot* of space once you start adding in a decent amount of sprites this way. For just sprite 0 or a few sprites, it's fine, but for bigger sprite overlays on static/special screens and sprite based HUD:s, it is not ideal. So here is an example script that is hardcoded to do title screen sprite overlays... does the job for this project.

Code:
VFLIP EQU #%10000000
HFLIP EQU #%01000000
LOWPR EQU #%00100000
	
LDA gameState
CMP #GS_StartScreen
bne +
	ldy spriteOffset
	repeatSpritePreload: 
	lda myOAMtable,y 
	sta $200,y 
	iny 
	cpy #4*10 ; 4 bytes per entry * number of sprites, but offset by 1 since we're counting from 0. 
	bcc repeatSpritePreload ;check if less than, if so repeat. 
	sty spriteOffset 	;just a precausion in case we want a separate upload using the original NM macros 
	+
jmp skipmyOAMtable	
myOAMtable:
;radioactivity sign 
.db (8*16)-5, $0e, 0, 8*1 
.db (8*16)-5, $0f, 0, 8*2
.db (8*17)-5, $1e, 0, 8*1
.db (8*17)-5, $1f, 0, 8*2
.db (8*18)-5, $41, 1, 8*1
.db (8*18)-5, $42, 1, 8*2
;trash bag 
.db (8*18)-1, $2a, 1, 8*8
.db (8*18)-1, $2b, 1, 8*9
.db (8*19)-1, $3a, 1, 8*8
.db (8*19)-1, $3b, 1, 8*9
skipmyOAMtable:

Add it to the top of PreDraw.asm and see what happens!

Here's what it looks like:
newpredraw.png



A bit of explanation is in order.

What we're doing here is storing a sprite table in the same raw OAM (object attribute memory) format that the PPU itself can understand. We copy that table to the OAM buffer. The game engine takes care of the rest.

address $200 is where the sprite buffer is stored in NESmaker.

the magic number #4*10 at line 13 specifies how many sprites we want to uplad.

The OAM format is as follows:
.db Yposition, tileID, attributes, Xposition.

.db is a directive that lays down a string of bytes typically meant to be read as data, in this case by the repeatSpritePreload routine.

Tips and notes:


on special sprite attributes and logic operators.
====

What's with the EQU statements?

these are aliases for special bitwise attributes you can use on the sprites. Instead of having to count bits, you can for example flip a sprite horizontally like so:

.db (8*18)-5, $41, 1 | HFLIP, 8*1

| is a logic operator. It ORs the palette id (in this case 1 or #%0000001 in binary) with what HFLIP represents, which is #%01000000.

The OR truthtable dictates that the resulting byte is #%01000001; only much more readable for humans this way. You get a clear idea what palette is used, and if any other attributes are set; separately though for the computer, it is one and the same byte.

Shouldn't all EQU statements be defined in the GUI user constants to be reviewable from the same place? Sure. but it's kind of a set and forget thing and good to bundle in here for didactic purposes.

HFLIP and VFLIP are sort of self explanatory. LOWPR (low priority) hides the sprite behind the three "solid colours" - it is the same hardware feature used by the "walk behind" tile script.

====
base 8 (or 16) and photoshop grid:
====
Instead of writing a position like so: 255, basing it on the tile or attribute grid makes it easier to hard-code.
I prefer basing it on the tile grid. so for example, position 37 would be 8*4+5. That tells me we're on the 4th row (or column), with an off-grid offset of 5.

I use photoshops' grid function to count rows in a sprite placement mockup. In the screenshot it is set at 16 pixels (attribute grid),

There is a caveat on the Y axis. Due to how the hardware works, sprites are drawn one line below what is specified. So if you want to be exactly on-grid, you need to lay down the Y position like so: myGrid*myRow-1


===
suggestions for increased versatility
===
As it is, it's just a static overlay uploader for the title screen. But with just a little modification, you can make it more universally applicable.

You can make the comments that tell me what the sprites are supposed to represent labels instead, like so:
trashbag:
.db -1, $2a, 1, 0
.db -1, $2b, 1, 8
.db 8-1, $3a, 1, 8
.db 8-1, $3b, 1, 8

that means i can reuse this data several times. Note that i made the positions relative instead of absolute. add these together with an absolute position of your choosing to "clonestamp" this metasprite anywhere.

You probably also need to make a variable out of the magic number on line 13 so you can decide when to stop uploading sprites to the buffer.

To prepare the routine for reusage with multiple data tables stored anywhere, you need to replace lda myOAMpage,y with pointers. Lastly, you need to prepare those pointers. Might make a tutorial on that some time, just not now.

Additional tips:
-the parantheses are redundant and can be removed if you don't like them
-when laying down bytes with .db, you don't need to use the # to declare a numeric literal. this helps tables be more readable.
 
Top Bottom