Those 2 weeks went by quick - it's time for an update! I don't know what form these updates will take, other than giving bits and pieces of the development process. You'll see graphics development, game design and decision making, snippets of assembly code, and more. I will warn you now - when I show code, you'll be in one of the 3 categories:
1) you are a talented programmer, and will probably see flaws, or inefficiency
(I welcome any advice if you'd like to share)
2) you have no idea what the code means
(if you are interested and want to start somewhere, check out
Nerdy Nights and
NesDev)
3) you have a little coding experience, and might apply some of my ideas to your own homebrew
(that's awesome)
Another warning about my code - it takes a lot of code to make things function correctly. I don't want to bore you and paste in huge portions of code, so you'll only see parts and pieces and I'll explain those snippets in plain english. You can always contact me and ask for more info. Finally, I want to recommend
this site which is excellent for referencing 6502 assembly language. If you see 3 letters in my code, like JSR or BNE, and want to know what the heck those do, you can look them up at
that site.
I imagine I'll reveal the name of this project very soon (maybe in the next update). In the beginning of a project, it's all about brainstorming. Coming up with game ideas is definitely a lot of fun, but also tricky. You have to know what the NES is capable of. Luckily, there are
over 700 examples showing what the NES can do. I'm a bit relieved that
Armed For Battle is completed, because I didn't know if real time strategy could be achieved on the NES. If you have an idea in mind, chances are you can make it, but you might just have to get inventive in how to implement certain things.
After finally deciding on the overall game I was going to make, individual gameplay ideas were jotted down whenever something more came to mind. My game requires levels that will move left and right only. I broke out the graph paper, and came up with a rough level.
Instead of a long winded explanation, I'll opt to just explain a few things about what you see above.
23C8, 23D0, 23D8, etc - these are addresses for Attributes
0, 32, 64, 96, etc (in pink) - these are the Y coordinates for sprites
0 through 15 across the top is for meta tiles (1 screen width is 16 meta tiles)
60, 24, 00, 52, 08, 28, 56, etc are numbers I assigned to meta tiles, and you'll see more about those numbers below.
Now you can compare the graph paper layout to what you see here:
I use
Tile Layer Pro to make my graphics. There are likely better methods for making graphics, but TLP is what I know. In TLP, you make individual tiles which cover an area of 8x8 pixels. A meta tile is a term that refers to an area 2 tiles wide by 2 tiles tall (in other words, 16x16 pixels). Picture each tile below having numbers. 00 in the upper left, and then count up as you go across to the right. The next row starts with tile 16 (or hexadecimal value $10).
After creating some tiles in TLP, I decide how to work with these tiles in the code. This is what my code looks like, when I'm creating meta tiles.
Now, let's put some of this together. If you look again at the graph paper, I drew an arrow pointing towards some green grass and wrote in the number "28." On the graph paper, I wasn't able to label it 28 until I decided how to organize my meta tile data (seen above). Once I wrote that code, and decided that a "Cliff Left Corner" would be value 0, Cliff Right Corner would be value 4, etc, then I eventually added "Grass Patch Left" and said it would use value 28. See the other numbers on that line? $0E, $0E, $0F, $13 (which is 14, 14, 15, 19 in decimal) are the 4 individual tiles that make up meta tile 28. If you look back at the tile layer pro picture, and visualize tiles 14, 14, 15, and 19 in the upper left, upper right, lower left, lower right, you can probably understand how my meta tiles are coded.
In another part of my code, I type in the level data. Here's a sample, along with a breakdown.
Each line of data is representing the level, 1 column at a time.
%11001010 - the % symbol is used when I want to type in a binary number. The reason I'm typing this number in binary, is because I want to carefully type in the individual bits. The 11 at the beginning is a special code. When my code accesses the level data, it goes through it byte by byte, and checks for certain things. Is the value = $FF? Is the value greater than %11000000 (aka 192 in decimal)? If so, the code needs to do something special. When it finds 11 at the beginning, it then looks at the last 4 numbers, which is 1010 (aka 10 in binary). Altogether, and in plain english, the %11001010 means 'repeat the next tile value 10 times'. It condenses things nicely. If I wanted to, I could simply say:
#META_INDEX_SKY, #META_INDEX_SKY, #META_INDEX_SKY, #META_INDEX_SKY,
#META_INDEX_SKY, #META_INDEX_SKY, #META_INDEX_SKY, #META_INDEX_SKY,
#META_INDEX_SKY, #META_INDEX_SKY
but then 10 bytes would be needed, rather than just 2.
#META_INDEX_SKY is a value of 36. In another part of my code, I just said
META_INDEX_SKY
= 36. I could have actually used the number 36 there, but using META_INDEX_SKY
just helps me read my code easier. Please don't ask why I then said "60" instead of META_INDEX_BOTTOMBORDER_CLIFF_TOP. I just found it easier to type in 60.
Finally comes $FF, which is the way I end each column. The code looks for $FF, to know when to stop getting data for a column.
I had no idea that this blog update would turn into something so technical, but for those of you that are still reading, here is a subroutine/function that I named DrawAMetaTileStraightToNameTable.
Here are a few random things I'd like to point out to other NES homebrewers.
- This code is used when filling in a full screen (NMI is disabled, so I can write straight to the nametables using $2006 and $2007)
- level_ptr_metaTileData is a pointer which is pointing to MetaTiles_Data
- I have found that pushing and pulling the X & Y registers at the beginning and end of a function (when you use those registers inside the function) helps eliminate potential bugs
- I'm used to coding in C, and it helps me when I add (nameTableAddr, curr_metaTileIndex, level_ptr_metaTileData), into my comments as if I'm passing parameters to the function
That's plenty for this update. I know screen shots are a lot more fun. Feel free to use the contact form, and send a comment my way. I'd be interested to hear whether this technical stuff is a waste of time, or if I should go a different direction with blog updates. Input is always welcome.