- MCP server with stdio transport for local use - Search episodes, transcripts, hosts, and series - 4,511 episodes with metadata and transcripts - Data loader with in-memory JSON storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
429 lines
35 KiB
Plaintext
429 lines
35 KiB
Plaintext
Episode: 487
|
||
Title: HPR0487: Demo or Bust 2010 Ep 6
|
||
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr0487/hpr0487.mp3
|
||
Transcribed: 2025-10-07 21:35:53
|
||
|
||
---
|
||
|
||
Where is my animation?
|
||
The time is 8.30, you're listening to WART radio, which means it's time once again
|
||
for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The time is 8.30, you're listening to WART radio, which means it's time for DemorBust 2010.
|
||
The ROM chips pretty much go to the two main chips.
|
||
The one on the left, I believe, would be the program ROM.
|
||
This is looking at the board from the top where all the components are facing up.
|
||
And the connector of the cartridge is on the bottom.
|
||
The one on the left is the actual program ROM of the program.
|
||
And this is mapped directly into the address space of the 6502.
|
||
I'll just call it the 6502 in the PPU from now on, instead of the 2A03 and 2C02.
|
||
So this is mapped directly into the memory map of the 6502.
|
||
The other chip is not program ROM, it's actually sprite ROM, which is mapped into the address space of the PPU.
|
||
Now, the program ROM is broken up into two 16 kilobyte chunks, bank 0 and bank 1.
|
||
Now, in the 6502, I'm bank 0 is mapped to address C000 to the top of the memory.
|
||
And bank 1 is mapped to address 800, this is in hex, address 800.
|
||
The reason for this, it kind of looks kind of funky, but the reason why we mapped bank 0 into the very top of memory is because if we have a cartridge that only has 116 kilobyte, bank of ROM, the reset vectors that tell the 6502 where to actually start in the IRQ vector,
|
||
telling the 6502 where to interrupt when there's an IRQ is in the upper part of memory.
|
||
So there has to be ROM there in order for the Nintendo itself to start.
|
||
So the Nintendo 6502 memory map has a lot of mirroring and it looks kind of funky, and this is one way it looks kind of funky.
|
||
Now, the other ROM chip that is in the cartridge again is the character ROM.
|
||
And this is maps into the very bottom of the PPU memory map in two 4 kilobyte chunks.
|
||
We call these pattern table 0 and pattern table 1.
|
||
Now, these possibly could be character RAM as well.
|
||
I'm going to describe firstly a very basic Nintendo system, just running Mario, because it turns out a lot of the complexities in the Nintendo is put into the cartridge with various mappers and bank sutures and all these things that are present in the cartridge were as the Nintendo itself is pretty simple.
|
||
Now, how the rest of the PPU memory map looks like is this? Well, of course we have these character ROM banks.
|
||
And this goes up to address 2000, hex 2000. Then we have name table 0 and attribute table 0.
|
||
We also have name table 1 and attribute table 1.
|
||
And then we have these two mirrors of the two name table slash attribute tables that I mentioned called name table, attribute table 2, name table, attribute table 3.
|
||
Now, how these two superfluous name table slash attribute table banks are mirrored to the prior two name table slash attribute table banks.
|
||
Depends on whether the cartridge is mirrored, said to be mirrored vertically or horizontally.
|
||
I think this was meant for horizontal scrollers versus vertical scrollers.
|
||
But if it's mapped horizontally, name table 2 gets the two bits get mapped to the 0.
|
||
That makes sense. And then 3 gets mapped to 1.
|
||
Then if it's vertical, 2 gets mapped to 1 and 3 gets mapped to 0.
|
||
Then we have the image palette and the sprite palette.
|
||
But let's go back a little bit to the name tables.
|
||
I should mention that how things are on the Nintendo screen on the television when you play the Nintendo is you have a background plane that is scrollable by some horizontal amount or some vertical amount.
|
||
And then you have sprites over that. You have a background in sprites pretty much.
|
||
And the background is made up of two name tables.
|
||
Two 32 by 30 arrays, two dimensional array of 8 by 8 sprites.
|
||
And so if we, the cartridge is mirroring horizontally, you can think of the name tables as side by side horizontally.
|
||
So that you wrap horizontally past 64 sprites and you wrap vertically past 30 sprites.
|
||
And if it's, if it's mirrored vertically, you wrap horizontally by 32 sprites and map vertically by 60 sprites.
|
||
If that makes sense.
|
||
Now how the name table actually stores these sprites that are in the name table is pretty straightforward.
|
||
It's just a linear index into the sprite number of these sprite data that stored in the character ROM.
|
||
And I will talk a little bit about the sprite data stored in the character ROM in a second.
|
||
But basically it's four color sprites in there.
|
||
So it's two bit colored sprites in there.
|
||
And the Nintendo gets the upper two bits because it's four bit color altogether.
|
||
It can show 16 colors in the background plane through the attribute table.
|
||
And each sprites in the attribute table represents a four by four sprite chunk.
|
||
And this chunk has to have the same upper two bits.
|
||
And this chunk is divided into four two by two sprite chunks.
|
||
And so the upper two, the lowest two bits in the attribute fight represent the upper left square.
|
||
The next two bits represent the upper right square.
|
||
The next two bits represent the lower left square.
|
||
And the last two bits represent the lowest, the low right square.
|
||
How the sprite data is actually stored in the character ROM is with 16 bytes per sprite.
|
||
And each byte is a horizontal little ending bitmap.
|
||
And so the first eight bytes is bit zero, this bitmap of bit zero.
|
||
And then you have the next eight bytes being bitmap of bit one.
|
||
And that's a sprite.
|
||
So let's take a break.
|
||
And we'll get back and sort of recap what we said and kind of give you a synopsis of what we said before we move further into the Nintendo.
|
||
The next two bits represent the upper left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the next two bits represent the lower left square.
|
||
And so the last two bits represent the more arbitraryного square.
|
||
And so the last two bits represent the lower left square.
|
||
And so the last three bits represent the lower right square.
|
||
This described in the previous segments is the basic architecture of the Nintendo.
|
||
We have two chips processor and a graphics chip called the Picture Processing Unit and
|
||
these chips have their own memory map independent of each other and two ROMs in the Gain cartridge
|
||
devoted to each one.
|
||
And we also describe how sprites are stored in the graphics chip and how they are referenced
|
||
with name tables and attribute tables to make up the background plane on the screen.
|
||
Now I do want to add very briefly, perhaps right now, there is a second bake of memory
|
||
that the PP has access to.
|
||
This is called the Sprite Attribute Table.
|
||
This is a 256-byte bank of memory that is used to describe where the sprites are over
|
||
the background plane, but we will get into that a bit later.
|
||
All the communication that the processor does by communication, I mean to the graphics
|
||
chip and the sound hardware and the controllers and whatnot is done through a bank of registers
|
||
that is mapped to address 2000 in the 6502 memory.
|
||
And in these bank of registers, we have a couple of registers, one of which is called the
|
||
PP memory address.
|
||
This is an 8-bit bank, specifically at address 2006 in HECS.
|
||
But this does is you supply the VRAM address to bytes because it is a word, it is a 16-bit
|
||
address.
|
||
The least significant, the high byte is written first and the low byte is written last.
|
||
And the next register in the register set is at address 2007.
|
||
This is the IO register.
|
||
You can write a byte to the PP memory this way or you can read a byte to the PP memory
|
||
this way.
|
||
And we talked about the Sprite memory.
|
||
There is a similar sort of style for accessing the Sprite memory.
|
||
We have at address 2003 the Sprite memory address, which is only 8-bit because we only have
|
||
256 bytes of this particular bank and the Sprite IO register at 2004.
|
||
In addition to those, we also have a third register for the Sprite memory called Sprite
|
||
DMA.
|
||
This is at address 2014.
|
||
This you supply, you write a byte to this and this byte multiplied by 256 equals the source
|
||
address for a DMA transfer into the Sprite memory and a transfer is all 226 bytes after
|
||
that address into the Sprite memory.
|
||
So let me briefly go through one by one all the registers that are in this IO bank to
|
||
give you a feel for what the CPU can control and how it controls it.
|
||
The first register, and this is starting at address 2000 in the CP memory map, and I'll
|
||
enumerate these just from now on.
|
||
And I should also add that when I refer to VRAM, I mean PP, the PP memory map, I may have
|
||
said that before, and I'll most definitely say in the future, so that's what I've been
|
||
when I say VRAM, I mean the PP memory map.
|
||
So the first register in the IO bank is the PP control register, so the first one, then
|
||
we have another PP control register, then we have the PP status register, the Sprite memory
|
||
address register, then the Sprite IO register, the background scroll register, the PP memory
|
||
address register, the PP IO register, then we have all the sound registers, which I won't
|
||
get into quite now, we'll get into that in a later part.
|
||
And the sound registers go all the way up to address 4000 14, then we have the Sprite
|
||
DMA register again, and after that we have the sound control register, then we have the
|
||
Joypad number one register, and Joypad number two register, and that's about it for
|
||
IO between the program and the rest of the system.
|
||
So let's have a look at the Super Mario Brothers.
|
||
Super Mario Brothers is a game with two 16 kilobytes banks of program ROM for the 6502,
|
||
as well as one bank of character ROM for the PPU, and in bank zero again the interrupt factors
|
||
are present, so let's examine what the interrupt factors are, we have three of those, we have
|
||
an IRQ and on maskable interrupt as well as a reset vector, the reset vector happens
|
||
to be 8000 as present in the ROM, this tells the 6502 where to begin, so let's disassemble
|
||
the ROM from address 8000, and we can see that the first thing that Super Mario Brothers
|
||
does is it turns off interrupts, it then loads hexadecimal 40 into the register at 2000,
|
||
which happens to be the PPU control register number one, and what 40 hex is the bitmap
|
||
of this correlates to turning the interrupt on sprite hits on, now the kind of going
|
||
back to sprites a little bit, the Nintendo has a very special sprite, this is a sprite
|
||
zero, which can be used as a what's called a hit sprite, what this means is that when
|
||
the raster, when the scanline encounters a pixel in sprite zero, which is not zero, it generates
|
||
an interrupt, this generally is used for being able to mark places on the screen where we
|
||
should change how the background is scrolled, for instance, with Super Mario Brothers specifically
|
||
what this is used for, not in this case at the very beginning because it's used as a
|
||
missile initialization at the very beginning, but later on in Super Mario Brothers, the
|
||
hit sprite is actually used for the menu at the top that has your score and all the status
|
||
for your little Mario character that's running around, and the hit sprite, when the raster reaches
|
||
that sprite, then we scroll the background, name tables, the background plane, to where
|
||
it would be in just normal gameplay, because you're moving this background plane, because
|
||
it's a background plane, because it's a 2D scroller, right, but you're not moving the status
|
||
at the top, so the status at the top is actually in the background plane, but it's not being
|
||
moved, because we're using the sprite hit interrupt as a reference to one to move it and
|
||
one not to move it. Now what we're doing here at the very beginning, I presume, granted
|
||
I am not a programmer from the 80s or anything like that, and so just by disassembling Super
|
||
Mario Brothers, I assume what the programmers were doing here was that they were turning
|
||
on the sprite hit interrupt, which doesn't actually generate an interrupt, because they turned
|
||
off the interrupt mask in a 6502 before doing this, but what it actually does for it allows
|
||
the PPU status register, which is also part of the 6502 register bank that can be read by
|
||
6502. There's a particular bit in here that goes to, that is set to one, when the sprite
|
||
hit occurs, whether we have that interrupt mask or not. So going on looking at the disassembly
|
||
of the very beginning of Super Mario Brothers, we see that the program is actually looking
|
||
at the PPU status register, and it is waiting until it is one. The hit occurrence flag is
|
||
the actual flag that this is, twice. I don't know why it's doing this twice, but it
|
||
waits until it's one again. Now I presume again, this is just my assumption,
|
||
based on looking at this program, is that perhaps that the programmers wanted to bring
|
||
the Nintendo into a state that was unknown, like completely known, because when you start
|
||
the Nintendo, you are unaware of where the Raster would be as compared to where your program
|
||
is. So maybe if your program depends on having a vertical blank interrupt occur at a particular
|
||
time in initialization, or before particular time in initialization, it's helpful to know
|
||
exactly, have everything exactly in sync, how you assume the Nintendo is. Of course, this
|
||
is speculation, but this is what I think you're doing. So let's skip all the initialization,
|
||
and let's go into the actual game play, one you play, Super Mario Brothers. What we have
|
||
is a screen with the menu on top, and the actual game field on the bottom. Again, we have the
|
||
hit sprite just below the menu. And what the main loop of Super Mario Brothers does is it's, it
|
||
moves the background plane, scrolls it horizontally to zero, waits until we hit the bottom of the
|
||
menu, scrolls the horizontal by a modulus of where you are in the game map of a modulus of the
|
||
size, full size of the name tables, so that we wrap the horizontal scroll on the name tables.
|
||
As you move forward, then we wait until a vertical interrupt, and then we scroll it back to zero,
|
||
and do this all over again. Now, when you move forward in the game, what it does is it updates the name
|
||
tables below your moving window to represent where you are in its own internal map, and it does
|
||
by updating the name tables first, then it updates the attribute tables. All the while updating,
|
||
the player information where you are, where the monsters are, and checking to see if the status
|
||
of the controllers has changed. Now, all the monsters are done with sprites, and Mario's done
|
||
sprites as well. The coins that we have that are fading in and out, it just adjusts the palette
|
||
for this, for the question mark boxes, where we have this shiny gold that is shining in and out,
|
||
it just cycles through gold-ish looking colors for the palette, and that's how that's done.
|
||
Now, we can have 64 sprites above the background plane more or less simultaneously.
|
||
The attributes for these are stored in, again, the sprite attribute table, which is a 256-spite
|
||
bank of memory that's accessible by the PPU as well as the 6502 through the DMA register as well
|
||
as the sprite address and sprite data registers. The sprite information looks like this. We have
|
||
four bytes per sprite, the first byte being the Y coordinate of where the sprite is, the second byte
|
||
being the tile index. The third sprite is a bitmap of flags indicating whether the sprite is
|
||
flipped vertically or whether the sprite has priority over the background. Now, what priority
|
||
over the background means is, while there's a special color in the Nintendo, color is zero,
|
||
this color is used for transparency. If the sprite color is transparent, we default if it has a
|
||
sprite, if the priority is over the background, we default to drawing the background.
|
||
Now, if the priority is one being behind the background, and the background color is not zero,
|
||
we default to the background color, and if they both happen to be zero, there is a background
|
||
register color in the register bank, and we default to that color. Now, the fourth byte
|
||
for each sprite indicates the X coordinate. Now, I should mention that we can have eight by eight
|
||
sprites, but we can also have eight by 16 pixel sprites. This is used in games like Castlevania,
|
||
for instance, and the only real difference between these, aside from the size of the sprite,
|
||
is the sprite tile index number. No longer is a linear index into the character ROM
|
||
over the sprite is, but rather, this value is both significant bit, is assumed to be the least
|
||
significant bit, and the least significant bit is ignored, if that makes sense.
|
||
So, then the sprite data is stored in eight by eight sprites,
|
||
linearly being the top part of the eight by 16 sprite, and the bottom part of the eight by 16 sprite.
|
||
The advantage of this, of course, being now we can have a screen that appears to have 128
|
||
by eight sprites, but in reality, it's 64 by 16 sprites. Only eight sprites per scan line
|
||
can be displayed, which is one exception on the amount of sprites that can be on the screen at any time.
|
||
You can see an artifact of this when you're playing, and there's a bunch of goombas next to you,
|
||
or some sort of enemy next to you or monster next to you, and you and all the monsters kind of
|
||
blink a lot. I don't know if you've seen this, but play the Nintendo, and you'll probably see this,
|
||
when you have a bunch of things there together, this is because you're exceeding the maximum number
|
||
of sprites that can be on the scan line at one time. There are a lot of emulators that ignore this,
|
||
but you'll probably see it on a real Nintendo. Now both the backgrounds and the sprites have two
|
||
palettes, and these palettes are in the PPU memory map. Again, H1 is an array of 16 bite entries,
|
||
and well, there are actually six bits entries, but the sixth and seventh bit of each bite is ignored.
|
||
These color entries in the palette don't actually hold any RGB values or anything like this,
|
||
but rather it is a bit map of the illuminance as well as the chroma-bloom chroma-red
|
||
of the pixel or rather of the palette entry, and there are two bits associated with each one.
|
||
So we have a choice from a supposed palette of 64 colors, where if the upper
|
||
luma bits are one, the colors are nearly white, whereas if it's zero, the colors have no luminance
|
||
to them. They're very saturated if that makes sense. On the chroma spectrum of this bit map,
|
||
on low values, we have a very low saturation, so we have a gray scale, more or less, and then on high
|
||
values, I haven't really figured this out myself, but on high values, we have all black. Not
|
||
exactly sure why we have all black on high values, but that's where we get black from.
|
||
And so the rest of the spectrum almost just looks like a pure chroma spectrum where we have a rainbow.
|
||
You of course don't have to figure any of this out. You can probably find the RGB values
|
||
of the Nintendo Color Map just by looking it up on Google if you want to put this into your emulator
|
||
or figure out what colors to choose for your game or something like that.
|
||
And so I think we've talked enough about video for the moment. I may get back to it,
|
||
but now I'm going to focus on the audio hardware in the Nintendo.
|
||
That was a intro by Cult Stars by Chris Covell. The Piat ID on this is 15216.
|
||
Now the sound hardware, which is, again, on the actual dive, the 2803, consists of four internal
|
||
channels, more or less. We have two square wave channels. We have one triangle wave channel,
|
||
and we have a noise generation channel. In addition to this, we can also do Delta code modulation
|
||
samples out of the Nintendo audio hardware as well. But for the moment, let me focus on the square wave
|
||
and triangle wave channels. All these channels, before including the sample channel, but we'll call
|
||
this channel five. Mind you can be either muted or unmuted by a register 4000, the register
|
||
in address 4,015 of the 6502 memory map. This is a five bit number, zero being mute, one being
|
||
unmuted. Each channel of the square wave channel, the triangle channel, the noise channel,
|
||
each of these have four bytes in the register bank associated with them to control them,
|
||
and they're all controlled in the exact same way. The four bytes for the first square wave
|
||
channel is mapped to address 4000. The second square wave channel is mapped to address 4000,
|
||
four. The triangle channel is mapped to 4000, eight, and lastly, the noise channel is mapped
|
||
to 4000c. Now, these for all time intents and purposes represent the same synth, the only
|
||
difference between the square wave, the triangle and the noise wave is we're dealing with a different
|
||
waveform, but the four bytes work the same way for every channel. The first byte controlling each
|
||
channel is called the control register, called control register number one. The bits in these include
|
||
a duty cycle. We have two bits representing a duty cycle from 25% to 87%, which is used to
|
||
simulate envelopes. Well, that's to simulate to have a primitive envelope or primitive frequency
|
||
shift. The next bit is a hold note flag, which can be used to hold the duty cycle of the frequency
|
||
shifts or continue the duty cycle of the frequency shift or the envelope. Then we have the next bits
|
||
which represents an envelope that is controlled by the cycle or an envelope that is fixed.
|
||
Then we have the playback rate, which if you wanted to, can be used to control the total duration
|
||
of the duty cycle. There are four bits associated with this. Now, the next byte is the control register
|
||
number two, which is a bit map again. The very first bits, the most significant bit, that's the
|
||
order in which I'm describing these from most significant bits, the least significant bit,
|
||
represents is zero if the frequency does not sweep over time. It is one if it does sweep over time.
|
||
Then we have three bits associated with the frequency sweep speed. Then we have one bit associated
|
||
with whether it shifts from low to high or high to low. Then we have three bits associated with the
|
||
frequency range in which this sweeps. Then the next byte is the frequency value. The total frequency
|
||
value is 11 bits. The lower 8 bits is mapped into this particular byte. The upper it is mapped
|
||
into the next byte, the last byte controlling each channel. The first three, the least three
|
||
significant bits in this byte are mapped to the most significant bits in the frequency value
|
||
register. The rest of the bits in this register is an indication of the active time. This gets
|
||
cut off after this time is expired, instead of having an envelope that goes down in volume.
|
||
Now I will be honest with you, my experience with programming the audio hardware is not as solid as I
|
||
would like it to be. I've just written an emulator for this, but you probably should find your closest
|
||
chiptune person and ask them about any questions that you may have with the audio hardware,
|
||
because I'm going to go into the depth that I know about the hardware in this episode. I'm not
|
||
going to go any further. The sample channel, the last channel that we're going to talk about,
|
||
has a similar sort of style of control. We have duty cycles again for the first control register.
|
||
We have whether this frequency will be held or not. We have whether this envelope will remain fixed
|
||
or decay over time, and we also have a playback rate. The next byte for the sample control is just
|
||
the volume. This is in 8th byte value, just controlling the volume of the sample. The byte after
|
||
that is the address register. This register represents the upper 8 bits in a 16-bit pointer to
|
||
where the audio is stored. After that, we have the length register. This is 8 bits that describes
|
||
the size of the sample. Now every time you write to the control register of the sample
|
||
channel, this triggers the playing of a sample. I'm thinking that's about all I'm going to talk
|
||
about with sound because I'm not entirely comfortable with the sound aspect of the Nintendo.
|
||
But if you write, I have a little bit of advice for you. If you write an emulator,
|
||
download it, no friendo. The sound core for the APU is what they call the audio processing unit.
|
||
It's really simple to use. Basically, it's a function that you call when you want to write to
|
||
any of these registers. Then you periodically call a function that updates a sample, a buffer
|
||
with what audio is coming out of the speaker. The core of no friendo can also be found
|
||
in the Nintendo sound format player called nose fart. Now, the Nintendo sound format is kind
|
||
of a hack of the program ROM data to completely get rid of all the game information and all the
|
||
graphics information. Just have it being played on an APU slash processor emulation.
|
||
The program knows fart, for instance, does this. People who make Nintendo sound format
|
||
files either do this with a tracker and this tracker writes a program that this emulator, this
|
||
half Nintendo implemented emulator runs and then it runs some sort of internal, through some
|
||
sort of internal format that this tracker uses for the program that it has encapsulated into the
|
||
NSF file. Or people extract the sound information from games like Mega Man, for instance,
|
||
how the sound is produced is produced via the interrupts, via the vertical interrupts of the
|
||
game. We have an address that we call to set up a particular song that we want to play with the
|
||
accumulator in the 6502 being the soundtrack that we want to play. Once that's done, the vertical
|
||
interrupt periodically calls another address to update the sound registers in the APU to actually
|
||
generate the sound. And this is how the music's done in Mega Man, for instance, Mega Man 1.
|
||
And it's similar for a lot of a lot of other games. So what people have done is they've found out
|
||
where the code that's specifically meant for sound is and they even encapsulated it in Nintendo
|
||
sound format files. This would probably be useful to you as a Nintendo programmer because if you're
|
||
generating an NSF file with a tracker, it's stored as a program. You need to find the initialization
|
||
routine. You can call this in your game program and then you need to periodically call a function
|
||
to update the sound registers. And that way perhaps you don't have to program these registers
|
||
directly. You can use a more intuitive way of generating sounds like with a tracker.
|
||
Now let's go back and talk about the Nintendo
|
||
so generally. We've just described a basic Nintendo system that is playing a cartridge with a
|
||
ROM for the 6502 and a ROM for the PPU. This is all well and good, but you are limited in the
|
||
amount of characters you can have on the screen as well as the size of the program. And over time,
|
||
people have overcome these limitations by putting into the cartridge things that are called
|
||
mappers or bank switchers. And what these are are chips that look at the address bus and when the
|
||
address bus of the program ROM gets accessed at key points, this either triggers the bank switch
|
||
of the program ROM or the bank switch of the character ROM or other things to extend the amount
|
||
of storage that can be put into a cartridge. Modifications to the cartridges also include things
|
||
like character RAM, for instance, where we don't have character ROM and then it's the program ROM's
|
||
responsibility to initialize the character RAM with characters. Supermire Brothers 2 does this,
|
||
for instance. And for a lot of the animated characters like the cherries that swing back and forth,
|
||
it's not accessing the name table of the background where these cherries are stored on the screen,
|
||
but rather it's accessing the actual sprite data and overwriting this with another frame.
|
||
That way, you don't have to heat track of where cherries are on the screen. You can just
|
||
overwrite the source of how cherries get drawn. Another game that uses this, for instance, is,
|
||
again, Mega Man 1. Now, the most common mapper is mapper number 1, which is a mapper that is made
|
||
by Nintendo Corporation. And this is a program ROM bank switcher as well as a character RAM bank switcher.
|
||
So if you write an emulator, first you probably should write a base system and then probably you
|
||
should write emulation from mapper number 1. Now, going back to the base system again,
|
||
how do we read controller information? Well, we read this through 6502, a couple of registers
|
||
in the register bank in the 6502 memory. The addresses of these two is 4,016 as well as 4,017.
|
||
4,016 representing controller number 1 and 4,017 representing controller number 2.
|
||
Now, how you access this is you write 1 to register 4,016 or register 4,017 depending on what
|
||
controller you're accessing. What this does is, while inside the controller, there is a shift register
|
||
that shifts out 8 bits, each bit associated with the button that's being pressed. If you write 1,
|
||
this resets the shift register. Then you can read sequentially strobing out each bit of the
|
||
shift register. The first read is a, then b, start selects, up, down, left, right. And this is how
|
||
joysticks work. Now, I'm not going to talk about the zapper, unfortunately, because I have no
|
||
experience with using the zapper. But let's now talk about the corks of the Nintendo.
|
||
The sprite memory address register as well as the ppu address memory register is basically
|
||
the same latch, so that if you write to the sprite memory address register, it's exactly like
|
||
writing to the ppu memory register and vice versa. If you write to the sprite memory address
|
||
register, it's clears the, it resets what's byte is being written to the ppu memory register,
|
||
so that the byte that you just wrote happens to be the lower byte, if that makes sense.
|
||
Another cork is generally you're not supposed to write to any of the ppu memory while the display
|
||
is being drawn. This is something that you reserve for the vertical blank. This is because internally,
|
||
the ppu uses the registers, it's registers as a scratch pad for actually drawing the image.
|
||
The advantage of this, however, is that it's a little bit of a hack, but you can
|
||
write to these registers while the raster is being drawn. And you can do things like squeeze
|
||
vertically the image size. This is, I've seen this done in demos, for instance, for
|
||
having objects that look like texture maps that are being rotated along the x-axis.
|
||
This is done by squeezing the entire display vertically to have it simulate how the texture map
|
||
would look like as it becomes, as the surface becomes perpendicular to the screen.
|
||
Another thing you can do is if you're very good at keeping track of time, you can write the
|
||
horizontal scroll of the background plane while it's being drawn to create parallax effects and things
|
||
like this. Another tip for emulator writers, when you write Nintendo emulator, chances are your
|
||
bottleneck is going to be ppu emulation. What you want to do is not emulate three clock cycles
|
||
of the processor and then emulate one pixel of the ppu because the ppu draws a pixel for every
|
||
three clock cycles of the processor. Going back and forth like this will kill your cache coherency
|
||
and will make your emulator dog slow. What you want to do is emulate the amount of cycles for
|
||
an entire frame because most of the communication between the ppu and the cpu is one way the only
|
||
communication you're getting back from the ppu is the hit flag interrupt which you can emulate
|
||
separately within this portion of the emulator. Then you want to next emulates a full frame of the
|
||
ppu and this will speed things up considerably. Another tip is to instead of evaluating a background
|
||
pixel and then evaluating a sprite pixel for every pixel, evaluate all the background pixels
|
||
to again increase locality of your program flow. Then after that,
|
||
that evaluates all the sprite pixels and then go through some sort of code to decide which
|
||
pixel gets strong. This will also speed things up considerably. I think that's going to be it
|
||
for this episode. We're getting a little bit long on time and I hope that this helped you in
|
||
any way or you found it interesting. I hope this wasn't too boring. Unfortunately, there is so much
|
||
information to divulge with an Nintendo. We haven't even scratched the surface. It's a very,
|
||
very interesting little piece of hardware and writing an emulator is probably one of the funnest
|
||
things you can do. So thanks for listening. We're going to close with not an Nintendo song unfortunately
|
||
but this is a song by the the Black Lotus that I am in love with for whatever reason. I'm
|
||
totally going to marry it. Like I don't know why I like this song so much but I really do.
|
||
So thank you much and we will see you next week. Take care.
|
||
Thank you for listening to Half the Public Radio.
|
||
HBR is master by caro.net so head on over to C-A-R-O dot-N-C for all of us in the
|