[a / b / c / d / e / f / g / gif / h / hr / k / m / o / p / r / s / t / u / v / vg / vm / vmg / vr / vrpg / vst / w / wg] [i / ic] [r9k / s4s / vip / qa] [cm / hm / lgbt / y] [3 / aco / adv / an / bant / biz / cgl / ck / co / diy / fa / fit / gd / hc / his / int / jp / lit / mlp / mu / n / news / out / po / pol / pw / qst / sci / soc / sp / tg / toy / trv / tv / vp / vt / wsg / wsr / x / xs] [Settings] [Search] [Mobile] [Home]
Settings Mobile Home
/vr/ - Retro Games

Thread archived.
You cannot reply anymore.

File: 1419712686638.png (4 KB, 150x219)
4 KB
After about a month and a half of learning 6502 for programming NES games, I realized I never did ask /vr/ for advice on the best way to learn. While I'm starting to get a good grasp on manipulating the op codes for the CPU, I still don't know a lot about the specific areas in memory for the NES, consequently where I can store read-only data on the ROM, where the memory addresses for the system's RAM are at, and how to write to the VRAM for displaying images.

Could any kind soul in /vr/ point me towards a reference to this kind of information? I feel a written guide might be better than me attempting to reverse engineer already existing code.
SNES is unironically easier than NES. NES had a lot of weird constraints on the memory map.

anyway, feel free to ask questions. i'd be happy to answer them.
The concept of the memory map is my big holdup right now. I practiced just using the instructions on the easy 6502 guide (https://skilldrick.github.io/easy6502/), but actually translating it into a practical use by knowing what memory addresses I can write to when programming for the NES and what sort of constraints I need to keep in mind is a hurdle that I can't find a good explanation for. I was using https://en.wikibooks.org/wiki/NES_Programming/Memory_Map to get an idea of where memory addresses are in the NES, but I don't quite get how to store data in the PPU (And consequently draw to the screen) and how to store data for mechanics in system RAM.

I'm probably not even phrasing that right, but essentially I'm trying to learn the manipulation of graphics rather than just running code in the background since without some sort of audio/visual cue, I have no idea if anything's actually working or not.
File: 6502.gif (15 KB, 625x943)
15 KB
>memory map
a CPU has a sets of pins called an address bus and data bus that are used to access external memory (as opposed to internal memory, like the 6502's A, X, Y, P, S, and PC registers). in the simplest designs the address bus outputs a binary number in parallel on all its pins, while the data bus reads or writes a binary number in parallel on all its pins. in this simple design the number of address bus bits determines the size of the CPU's address space.

for instance, the 6502 is a simple design that has 16 address pins and 8 data pins, and thus it has a 16-bit address space spanning addresses [0x0000,0xFFFF] that address bytes in the range [0x00,0xFF] for a total of 0x10000 bytes of addressable memory.

the job of a system designer is to connect the CPU buses to external memories, which also have an address bus and data bus in addition to a chip enable pin (and optionally a read/write pin for RAMs). the CPU data bus is directly connected to the external memory data buses, the CPU address bus is wired in creative ways to external memory address buses, and the chip enable pins are used to ensure only one device controls the data bus at a time. the way CPU address maps to external memories defines the memory map of the system.
File: poop.png (7 KB, 400x384)
7 KB
for example, suppose you had a ROM with a 15-bit address space wired to the 6502 with the 16th CPU address pin left unconnected and the ROM always enabled. now step through the address space of the CPU and ask yourself what address of the ROM does this correspond to, that is, what is the memory map? you'll discover the CPU sees two "shadows" of ROM.
CPU [0x0000,0x7FFF] -> ROM [0x0000,0x7FFF]
CPU [0x8000,0xFFFF] -> ROM [0x0000,0x7FFF]
if you had a second ROM2 and wanted to map it to the upper half of memory, you connect the ROM2 address bus to the CPU like the first ROM, and tie the ROM2 chip enable to the CPUs 16th address bit and the NOT to the first ROM chip enable, so the memory map is
CPU [0x0000,0x7FFF] -> ROM1 [0x0000,0x7FFF]
CPU [0x8000,0xFFFF] -> ROM2 [0x0000,0x7FFF]

for more complicated memory maps, the chip enable circuits get more complicated, but the idea is the same.
File: NES_memory_map.png (60 KB, 803x325)
60 KB
you can also map external hardware registers to memory, in a technique uncreatively called memory mapped I/O. this is how PPU registers in the NES are mapped to the CPU's address space. in this way, the memory map tells you where the CPU can go to flip some switches that change the behavior of the external hardware. if you want to draw something to the screen or make some boops, you look up where the interface for that hardware is in the memory map, learn what controls that interface provides you over the hardware, and then write a program that flips the switches in the appropriate way to achieve the desired result.

i need to review the NES hardware before i post more on it specifically

generically, it might help to know how a game program is organized
>inb4 the "it's assembler not assembly, kiddo" laper
>how to store data in the PPU
CPU RAM addresses $2006 and $2007. The PPU has it's own $0000-$3FFF piece of RAM to work with, you send the address you want to access of it to $2006 in the CPU's RAM. Then you either read the info there by reading $2007, or write the info you want to $2007. To do the same with the OAM data, you want to put all the data in a block somewhere $XX00-$XXFF, then send the XX to $4014 and have it all dump at once. Yes, there are registers to do it like the rest of the PPU's RAM. No, you should never use them for the OAM. Ever.
>(And consequently draw to the screen)
Look up PPU nametables and pattern tables. You've got a lot of learning to do.
>how to store data for mechanics in system RAM.
Unless you're currently using the accumulator register for something else:
STA $0000
The SNES is not easy to code for which is why nobody does homebrew for it.
in your own words, what makes programming for the SNES hard?
it's fairly complicated, has a lot of registers and features and a relatively irksome, slow, and clumsy CPU. there's also a lot of programming choices you have to make for example three different background layers and several color depths. that's why Mega Drive homebrew is much more popular as it's a far more straightforward architecture.
I had pulled up a few different examples to play around with, the first being the one posted at the bottom of the page here (https://www.nesdev.org/wiki/Programming_Basics) that manipulates sound channels, which once looking up the APU reference, at least gave me an idea how to play back sound. I had to dig up a header and write some dummy sections into my code to get it to compile, but the end result was that I was able to change the volume and pitch and had a working NES rom compiled from cc65.

The next test project I grabbed was this one (https://github.com/NesHacker/DevEnvironmentDemo/blob/main/demo.s), which ultimately writes HELLO to the screen. I'm still a little confused by a few things though, such as the .segment "CHARS", which was a required section I had to dummy for the audio test or my program would not compile.

Obviously, CHARS holds some sort of graphical damage, appearing to be eight lines of eight bits that stores a simple on/off for if a pixel should be drawn to the screen or not; practically speaking, on a fixed width font, you can easily visualize what each sprite looks like just by using a unispaced font and pretending the 1s are white pixels and the 0s black pixels. But then I don't know how this data is stored or how its referenced by the rest of the program.
>a relatively irksome, slow, and clumsy CPU
its 6502 with memory segmentation to extend memory and a fully defined instruction set with a lot of nice addressing modes. it's easier than 6502 because operations have a more consistent set of addressing modes. the segmentation makes compilation difficult, but assembly is still easy because the only real constraints are that code can't cross bank boundaries. also, it might be slower than the 68k, but it has more addressing modes and uses fewer cycles per instruction. the big advantage the 68k has is a native multiply and divide instruction.

as with many tile-based graphics systems (mega drive included) you select a graphics mode that determines what set of layers and bit depths are available. then for any system you specify where to find the tile map and character graphics, load the data, and load palettes. any other special effects can be initialized with the suggested settings, which has a page devoted to it in the dev manual.

the system is easy to program. the only real challenge is that the audio hardware is driven by a co-processor that communicates with the main CPU through 4 I/O ports and no interrupt facility.
NES coding is easy until you get into bank switching which is a royal PITA.

>have to constantly be paging between the sfx/music/level data bank every frame
>also DPCM samples cannot be swapped in on the fly, they require a fixed bank and this bank must also inhabit $8000-$BFFF, you cannot put samples in $C000-$FFFF
>I don't know how this data is stored
Sits on the ROM until the main loop begins. Then it's loaded into the PPU's RAM.
>how its referenced by the rest of the program.
lda $2002
lda #$3f
sta $2006
lda #$00
sta $2006
ldx #$00
lda palettes, x
sta $2007
cpx #$20
bne @loop
This code uses the accumulator to set the starting PPU RAM address, then load the data from palettes into PPU RAM. It then increments X, and checks X against 20. If it matches, it breaks out of the loop. Otherwise, it keeps loading. The same is done with the "sprite" data for the text.
@loop: lda hello, x
sta $2004
cpx #$1c
bne @loop
This loads the data into the OAM using the manual method, which isn't recommended. It's just done this way here so you don't have to move the data to the CPU's RAM before sending it to the OAM RAM.
pretty much everything besides the most shitty of games requires a memory mapper
>also, it might be slower than the 68k, but
FastROM games are about comparable in speed. The 65816 has higher IPS than 68000 so it can be clocked at a lower speed for the same performance.
This is why UNROM games normally never use samples. Deadly Towers sported a reverse UNROM that fixed $8000-$BFFF so it could use them.
No, no. You've got it all wrong. People write games without mappers because it's more challenging. It's totally not because they can't into mappers. It's like you don't even scribe to the micro mages youtube channel.
you can't access PPU registers or RAM except during blank which is hard
Genesis is the easiest just because you can use C, and it has less weirdness with its video chip. (Why the SNES has so many redundant modes is beyond me.)
>Genesis is the easiest just because you can use C, and
for an RPG, yes. too slow for action games.
Yamauchi wanted to throw on as many gimmicky features as he could because Nintendo were late in getting out a next gen console and he didn't want to look like they fell behind Sega and NEC.
This was made with SGDK, looks fine to me.
the 68000 is def. easier to use especially its flat memory map and 32-bit registers even though most games won't need 32-bit calculations (plus they're slow).
a vey annoying limitation of SNES is that only 16k of the video RAM can be used for sprites. the Genesis lets you use as much space as you want even though in practice the background graphics use most of it up.
>except during blank
Is this a game where I'm supposed to fill in the "blank" with a word like "butt" or "poop" or are you just retarded?
File: 1588143736521.jpg (34 KB, 568x376)
34 KB
Vertical Blank
Disagree, otherwise there’d be a shit ton of SNES homebrew games
>Disagree, because the thing in my head said i should you know the thing
Zoomies. They really are that stupid.
Why do you even make comments like this instead of presenting an actual argument? It contributes absolutely nothing to the thread and 4chan is completely inundated with this sort of thing now, actively dragging down the quality of any discussion.
I’m pretty sure it’s just one loser who goes into threads and calls people “stupid” or “zoomer” looking for (you)’s

Delete Post: [File Only] Style:
[Disable Mobile View / Use Desktop Site]

[Enable Mobile View / Use Mobile Site]

All trademarks and copyrights on this page are owned by their respective parties. Images uploaded are the responsibility of the Poster. Comments are owned by the Poster.