catsoncrack1, I hope this doesn't sound rude, but it's clear by now that you have absolutely no idea what you're doing here... you're randomly trying things to see what works, and this clearly isn't working out for you. I mean, even if you got something to work by accident, you wouldn't learn much from that because you wouldn't know *why* it worked.
I suggest you take a step back and try to understand the basics of how the console works so you can better understand what needs to be done in order for the console to generate an image, and you'll have much better chances of writing working code.
The PPU generates images based on a set of configuration and a bunch of data. The configurations are things like "which set of tiles to use", "which name table to display", "color and grayscale filters", and so on. These settings are modified via memory mapped registers, you basically read the documentation about these registers
and write the values that will select the settings you want.
As for the data that the PPU needs, that's the pattern tables (the 8x8 bitmap tiles used for sprites and backgrounds), name tables (which tiles compose the background "grid"), attribute tables (what palettes color the tiles in name tables), palette RAM (which colors make each palette) and OAM (where sprites go, which tiles they use, and other sprite settings). All of these is stored in memory in different parts of the system, but, except for the OAM, everything appears to the programmer as a single chunk of memory
, which's very convenient. PPU memory isn't directly accessible by the CPU though, so you need to use a couple of PPU registers to access that memory (i.e. you tell the PPU where you want to store the data, then you send the data, and the PPU will take care of putting it where you requested).
The PPU registers used to access the PPU memory are visible at addresses $2006 and $2007 in the CPU addressing space, which the CPU *does" have access to. This is a bit complicated, bit this is how communication between different pieces of hardware in oldschool computer works: The console "listens" to accesses to special memory addresses and redirects these to the corresponding pieces of hardware. No need to think too much about this for now, just keep in mind that accessing memory and talking to other parts of the hardware looks the same as far as the CPU is concerned, the different is in the specific addresses being accessed.
The 2 PPU registers used for accessing PPU memory are called PPUADDR ($2006) and PPUDATA ($2007). The former is used to tell the PPU which address you're going to access, and the latter is what you use to transfer the data itself. Addresses are 16-bit, but the 6502 can only transfer 8-bits at once, so you need 2 writes to set an address. After that, you can write one or more bytes of data and they'll be stored sequentially starting from the address you specified. Example:
Code: Select all
;PPU, can you please point to address $3F00?
;PPU, can you please store $1A at the address you're currently pointing to?
and that's how you write stuff to PPU memory. A valid picture needs at least:
1- Tiles in the pattern tables. If you're using the NROM mapper, the pattern tables are automatically populated by the .chr file included in your project, you don't need to do anything else.
2- Name table pointing to the tiles present in the pattern table selected for the background. Each tile has an index, ranging from 0 to 255. A full name table is 32x30 tiles, so you need to write 960 bytes starting at PPU address $2000 (where the first name table is - don't confuse with the memory-mapped register PPUCTRL, which's visible in CPU address $2000) to have a completely filled name table.
3- Attribute table. Yeah, these are kinda hard to grasp at first, so be sure to write all 0s to the attribute table corresponding to the name table you're using (the first AT is at PPU $23C0). This will cause all tiles to use palette 0. A full attribute table is 64 bytes.
4- A palette. Since all your tiles will be using the same palette, just writing one palette is fine. Palettes start at PPU $3F00, so if you write 4 bytes starting from that address, that'll be the first palette.
Once all that memory is properly populated, you can set the scroll to point to the name table you're using (select the name table via PPUCTRL -accessible via CPU $2000-, and then reset the scroll to 0 by writing to PPUSCROLL -accessible at CPU $2005- twice) and turn background rendering on.
Does this make sense so far? If not, please ask anything you want here and we'll try to make things clearer for you. Writing your first program can be hard if you're not familiarized with the concepts of retro computer architecture, but resorting to random guesses can be really frustrating and can even teach you the wrong things. If you have a basic understanding of how things work, you can at least come up with theories on how to achieve your goals, and make educated guesses about what code you need to write.