I originally started this post a little more than 3 months ago. Two things have happened since...
- Not long after starting, I realized how sick I was of coding in
Assembly (a result of my Computer Engineering Technology degree). I had
abandoned this project to simply focus on games, making small projects
in Unity and Unreal.
- A few days ago, I received approval to create a fully functioning
NES cartridge as my Senior Project. Hence, I am putting Unreal and
Unity back on the shelf to put more focus back onto this project.
Hopefully, the result of the above events will result in a blog
post AT LEAST once a week (as I will have to attend class to work on it
anyway. The ultimate goal now is to (hopefully) design an original
game, and look into the equipment required to write it onto a cartridge,
and write a paper reviewing my research and methodology.
--- Original Post Below ---
This post will be based upon
Week 3 of the Nerdy Nights Tutorial, as well as diving further into the 6052 processor.
As
I already have some familiarity with assembly programming, I may skip
over some of the basics. If I somehow manage to get people who want to
know more, I'll update.
The 6052 Processor
The memory addresses of the 6052 processor are divided up as such:
- $0000 - $0800 = Internal RAM
- $2000 - $2007 = PPU Access Ports
- $4000 - $4017 = Ausio and Controller Access Ports
- $6000 - $7FFF = Optional WRAM (read from cart)
- $8000 - $FFFF = ROM (read from cart)
The last set of addresses ($8000-$FFFF) will store the bulk of our code.
Like other microprocessors during this time, the 6052 has 3 key 8-bit registers that will no doubt be used frequently:
Accumulator (A), and Index Registers X & Y.
The accumulator is typically used to store data and perform basic math
operations, while the two indexes are ofthen used to keep track of
loops, counting, or accessing memory. There is also a
status register that hold information about the most previous instruction the CPU performed.
Assembly Code Structure
This
part of the post may require some research before I post any notes. It
appears for the purpose of emulation, we will be using an assembler
known as NESASM3. Below will be a few new concepts that will be required in each programfor emulation.
I have highlighted a few topics topics so that I may come back to them and add more info.
- iNES Header
- This
16-byte header provides all the necessary information to the emulator
concerning the specs of the game, including mapping, graphics mirroring,
and PGR/CHR sizes.
- This is not necessary for real hardware usage.
- Banking
- The
6502 processor breaks the 32kB limit of code into 8kB "banks". I will
need to revisit this in the future to understand the importance of using
these banks.
- Vectors
- a.k.s
"Interrupts" - There are 3 occurrences when the NES will interrupt your
program to jump to a specific point. Those points are assigned the
following tags:
- NMI Vector: Occurs every frame, PPU is
letting the processor know that it is open for graphic updates (enterng
the "V Blank"[1] state).
- RESET Vector: Called everytime the reset button is hit or when the NES is powered on.
- IRQ Vector: Typically controlled by the mapper. Need more info on this (not being included in Nerdy Nights tutorial).
- Each of these interrupts must appear in the PRG code, even if it is not being used.
I
am considering scanning my notebook page where I printed off the Nerdy
Nights "background.asm" example code and made annotations, as I feel it
would be better seeing each of the above code snippets in context.
Maybe I will just make that a separate blog post.
The next Nerdy
Nights lesson goes more in-depth on the PPU. I will save the code
overview notebook post until after I share those notes.
Cheers,
-JWest
[1]
The "V Blank" state is the period when the PPU refreshed the screen. I
don't recall if I had already clarified that term before this post or
not.