It's crazy how such an obtuse and unintuitive subject can become simple and clear through just proper explanations and simple diagrams. Thank you for your work.
programming, in general has that reputation because people just don't explain it properly... assembly and other low-level cocepts tend to have it worse since they're considered "obsolete" in most applications [till you mess with drivers, compilers, NEW systems, embedded systems, so on] i'm personally starting to see assembly and whatnot as being positively more SANE than C++ and its derivatives.. they still can be hard without the right sources of documentation, but the only real difference is there's a lot of manual memory management, and it takes many small steps to do something that seems 'simple' in other languages. i admit it's scary that you could so easily cause a fatal exception and totally crash the machine, but i somewhat prefer that over the abstractions and crap built-into C++ and the likes not sure if i'll ever touch SNES homebrew or hacking, but this is an awesome series, and i do find it quite interesting actually being able to LEARN how this stuff works. One of the big turn-offs for me is that finding good documentation is next to IMPOSSIBLE. [btw, don't lookup windows exes...] i've currently been looking into 68k assembly and trying to reverse-engineer a NEO-GEO game. that's... umm...interesting. So far, documentation on the system is pretty good. My gripe is the CPU... I have currently three major sources of documentation I'm using, all for specific purposes... >.> [Which is why I have not touched this particular project for months until now.] Ofc, the M68K is actually a fairly complicated processor, but it certainly isn't as bad as x86! I'm slowly starting to grasp it better. At least there was thought into what kinds of complicated instructions were really necessary. One of my least favorite x86 things to actually try and understand is/was "repeat not equal scan a string of bytes" aka repne scasb. I kinda get it now, but not personally one of my favorite opcodes to stumble upon... It's one thing to say "this is how you get the length of a string" [its main use]. It's another to break it down and EXPLAIN what, exactly it's doing... I have a few windows games I'm looking at, but I'm a bit burnt-out from the combination of x86's nightmare fuel instruction set and the way windows executable files work behind the scenes. It's just not fun... Good news is what I was doing this for was mainly to break-apart resource files, which I'm slowly figuring-out on my own. [and with some help] I could probably code the logic for one of these games by myself, now. The others might require some research, but it's certainly faster than slowly working-through assembly code. Anyways, the content on this channel is pretty top-notch. The world needs more like it. Maybe assembly wouldn't scare people so much, and maybe homebrew development and/or ROMhacking would be more accessible, if the resources were actually OUT there to explain it in a manner that's easy to digest. So far, they're quite lacking... I know assembly used to completely terrify me. And then I discovered the small handful of places that explain it in a way that it may be understood. [from my experience, it's usually not those technical manuals] I'm nowhere in a position to be completely proficient with it, or make use of it, but I'm learning, slowly. It's overall a pretty fun process. It can be stressful or frustrating, but it's exciting to learn about, especially actually be able to understand even a fraction of just how our computers manage all the complexity that most of us would take for granted.
Yes, but actually no. The audio videos are going to be split. The next one will just be about how it interfaces with the rest of the system. Or so I hear.
@@henke37 If that is the case then I can understand why. Like how the Super FX chip and other peripherals are going to be covered in a sperate video as mentioned in this one. To which I'll do the same as I've been doing. Waiting patiently while also enjoying any other content that comes down the pipeline.
@@renakunisaki It's such a shame that they underclocked the CPU for that, but were too far along in development to reverse it when they cancelled the feature.
@@aaendi6661 Well, if the programming techniques known to the programmers at that time were completely unorthodox to how the CPU should be programmed, is it the designer's fault or the programmers' fault? For me, particularly, the best thing they did on the GBA was putting an ARM processor.
Now imagine, on NES you only have the first column of this graph, 0000-FFFF, so only 16-bit addresses. This 64kB area is then broken down similarly: 0000-07FF - 2kB Work RAM 0800-1FFF - Mirrors of Work RAM 2000-2007 - PPU registers 2008-3FFF - Mirrors of PPU registers 4000-401F - APU (sound) & Joypad registers, Factory testing registers (locked without modding) 4020-7FFF - Not mapped / Open bus (typically used by extra Work or SRAM and more advanced MMC chips) 8000-FFF9 - Cartridge ROM (an MMC chip in the cart if any, is responsible for banking the larger ROM into this area) FFFA-FFFF - Interrupt Vectors
One of my favorite channels on TH-cam. By far. Not only is the content niche and extremely interesting, but the delivery and presentation is absolutely exceptional. Keep it up!
You also don't "need" to know about history, art, geography, and so on... After all, you just need to know how to open your mouth and throw pringles in there... You will go very far in life with such mindset. Let me guess, another millenial?
I remember realizing that AR and Game Shark codes were all just hex code injected into games. I knew much less about computers/programming then, but it was def a profound realization lol
I'm glad you explained *why* all the different mapping modes exist. It seemed unnecessarily complicated to me when I read it (compared to the Genesis, for example, where the map is almost always the same), but having different modes for different tradeoffs w.r.t. data contiguity and access time makes a lot more sense.
It's too bad 99% ended up just using long addressing for everything in SNES, throwing any speed benefit from the way nintendo organized memory out the window.
*FOR THOSE ASKING ABOUT 'WHY MIRROR RAM'* From what I got (I'm no expert, but I have at least some understanding of memory and programming) .... picture a Playstation Game on 4 discs. Say, FF8. As you go through the game, you can revisit older areas. Why? Because those older areas' data are mirrored on the later discs. If they didn't mirror the older areas' data, then you would get a "Please Insert Disc 1" every time you wanted to step into Balamb Garden, for example. The memory mapping works much the same way: If you're working in a specific area of the RAM, it is much slower to jump out of that section, and into another section to find the data you need. UNLESS, of course, you copied that data and mirrored it into several different sections. Now, they didn't mirror ALL of the data, only some of it, just like in FF8 .... dialogue and cutscenes, for example, the FMV video that plays during the assault at the beginning of the game only exists on Disc1, as does the FMVs where Squall is dancing with Rinoa. Why? Because you'll never see that cutscene past that point in the game, no point in copying that onto the other discs. But, Balamb Garden's assets need to be copied onto 3 of the discs, because it is possible to visit Balamb Garden at multiple points in the game. You don't want the player switching discs constantly, so you copy some of those assets that you think the player will be needing periodically throughout the game. Make more sense?
But the whole point of RAM is that it allows random access... I'm not sure what it means to "jump out of" a section of RAM, I'm not sure that makes sense. Are we talking about caching, or segment registers, or what?
@@thealliedhacker If you saw earlier in the video, you address different parts of RAM with addresses. $AABBCC format where AA is the pointer to what section of RAM you're working in. Let's say there's an address that you need some data from at, say, 01AAAA. You could just simply write "AAAA" (which saves you 2 letters in the code) and if you're already working in area 01XXXX, the 01 is implied unless specified otherwise. But what happens if you're working in area 07XXXX and you need the data that's stored at 01AAAA? You'd have to code your instruction to specify 01AAAA every time you want to point to that data. Unless of course that 07AAAA is mirrored and is the same as 01AAAA. Then you could, in fact, just write AAAA and you'd get the same data (you'd be jumping to 07AAAA but that's fine, because 07AAAA has the same data as 01AAAA). EDIT: Also, correct me if I'm wrong, but if you're working in area 07XXXX and you specify that you wanna go to 01AAAA for data, doesn't the implied area change to 01 so you'd have to again change it back to 07 to return to area 07?
@@Dhalin Well, that just sounds like we're trying to save memory by reducing the size of the instruction, not that the instruction will actually take longer to execute. It still seems like the speed is the same, unless decoding the longer instruction is slower or switching the bank has its own intrinsic cost for some reason...
@@thealliedhacker Well, if my edit is true, then it would also take extra instruction time to swap whatever the "current" area of RAM is, too. There's probably more to it, in the actual circuitry, a millisecond here, a millisecond there, I mean, a lot of SNES games lag as it is when there's too much going on, so I'm sure they did these things for a valid reason.
@@Dhalin Well, I assume it wouldn't require an extra instruction to move back though, since the next instruction could also just use an extended address, so we still wouldn't lose any time...? I dunno, maybe the main factor is just saving the space in the instructions.
I have a hard time entirely understanding these videos, but in every one I learn a little bit something new about the wonderful SNES. Keep up the good work.
I'm the most hardcore kind of gaming nerd and I didn't realize until I read out this comment from Tails19935: "Oh boy, next one is going to be about the SPC-700. I've been anticipating that one."
The funny thing is that, Nintendo spent all this effort designing the memory map so programmers could use 16-bit addressing mode, yet 99% of programmers went with long addressimg mode for everything anyway.
Turns out developer time is a finite ressource too, and more costly than hardware. Also, hardware designers have a very bad habit of poor documentation. I do remember many early SNES games lagged unnecessarily because of this.
I’m not even gonna pretend I can understand everything you’re talking about, but I still can’t get enough of your videos. You are too good! Keep it up.
One thing to add is that the cpu can have 24 bit instructions. But works faster if you restrict yourself to instructions using only 16 or 8 bit addresses. This makes it useful to layout the memory in such a complicated way
@@aaendi6661 I get your point but also remember that SMW is a launch game (it also was slightly rushed, IIRC) and the 65c816 processor is a rarely used processor it makes sense why it used unnecessarily long addressing (at least the lack of data bank shenanigans). Of course, it also uses (sometimes) long addressing when it isn't absolutely necessary (either same data bank or data bank switch is faster) which is where I get the "overused" part (I still believe you make mountains out of molehills, though).
@@aaendi6661is it possible to make some kind of expansion like the Super Game Boy but for NES games? There would be a NES CPU, PPU, and RAM (somehow condensed idk) as well as a NES cartridge port. I wonder if the NES APU could be played alongside the SPC700. Not sure how the Super Game Boy does it (if it even includes the LR35902 sound at all, I should've searched this up before writing)
Yeeeeeeeeeaaaaaaahhhhhhh! More technical-ness! Btw, do you think you will do the Sega Genesis after the SNES? I was just wondering bc I am intrigued about it.
Some Game Boy games might have had those null buffers too. I always wonder if they contain anything interesting. Even a ROM dump usually won't include them, unless it's done by extracting the actual chip. (The GB games would be any that use MBC1 chip with more than 1MB of ROM. But I'm not sure any exist... 😅)
I can't wait until 2020 when you will cover the S-DSP and SPC700 and we will see the true extent of pitch modulation, white noise, the delay module, and what's up with that BRR compression.
The more I learn, the more respect I have for Nintendo for sneaking all these workarounds in. They knew they effed up with their choice of a CPU (and their orphaned NES legacy), but they crammed in all the secret features they could to compensate. And when a developer actually USES them? The system punches well above its weight.
I still dont get why the Address space wastes so many addresses on mirroring why mirror if the entire 24bit space is addressable? is it to save clock ticks on higher address access? Just dont get the logic.
Incomplete decoding of addresses was a common trick to save transistors back then. The decoder circuit would only check the n highest or lowest bits of the address instead of checking every bit. Often, e.g. with smaller ROM chips, the excess high address lines were just ignored, which resulted in ROM mirroring over the CPU address space. And not many games used the entire ~8 MB theoretical ROM capacity of an un-switched SNES cart. They only started pushing this towards the very end of the SNES's lifespan. Super Mario World was only 512 KB.
For the RAM mirroring, yes. The 65816 instruction set was such that accessing data in the one "current" bank was 1 or 2 cycles faster, and took one less byte, than specifying a full 24 bit address. And the only way to change banks was with stack instructions (PHB,PLB,etc.) which were 3 or 4 cycles a pop (or push, hehe). Obviously this won't do during vblank, when you're in a tight race to get everything to the PPU for the next frame. So the solution was to have a small part of WRAM always visible in the same bank with all the I/O registers, so that if you structured your game's memory properly you wouldn't have to change banks often. ROM mirroring was mostly just because the ROM chips in smaller games didn't use all the available address lines. They only used the n lowest bits of the address and ignored the rest.
The LoROM seems similar to how memory mapping worked on the NES. If the program bank register is between $80 and $BF, the data bank register set to $80, and the direct page is set to $8000, the memory is almost laid out the same as the NES.
The 65c816 CPU inside the SNES has 3 extra registers for program and memory access: the Direct Page Register, Program Bank Register, and the Data Bank Register. Your question pertains to the Data Bank Register. The _DBR_ is an 8-bit register that specifies which bank data is accessed from when using a 16-bit addressing mode. So if the DBR has a value of $81, the instruction `LDA $2100` will access memory address $812100 . In short, the DBR acts as the high byte of the 24-bit address when a 16-bit addressing mode is used. Similarly, when using an 8-bit addressing mode, the _Direct Page Register_ is used. This register is 16-bit, so if the Direct Page register has a value of $7E00, the instruction `LDA $2D` will access address $7E002D.
@@haruki_nyan Except direct page doesn't represent the high and bank bytes but rather, it is the base address and the address on the opcode is an index to that base address with $00 as the bank. Sounds complicated but it's really just addr + DP on bank $00 so $7E00 on $2D actually results in $007E2D (usually not mapped to anything) instead of $7E002D. And if DP were, $00D3, you get $000100 on `LDA $2D`.
All this block mirroring stuff makes me wonder if there is something going on that I don't know about. For example, is using a 24-bit address sufficiently burdensome that trying to use a 16-bit address within the same bank is preferable? Besides the obvious fact that 24-bit memory instructions are 32-bits in size, and the difficulty of assembling a 24-bit address from two registers. That's the only reason I can come up with for why mirroring would be so frequently used, when you could just have more available storage in the ROM.
This is super interesting and really helps me understand how mashups like Zelda/Metroid randomize works. One question for you: I thought Star Ocean used ExLoROM but you said it was never used by official games. What Map does Star Ocean use? Thanks again! I love the series!
Well, if the game is bigger than 6MB, and if ExLoROM wasn't used commercially, then the only other choice would be ExHiROM. That, or they did some bank-switching magic like they used to do in the AT2600 days. I dunno if that's possible on a SNES or not, so just throwing theories out there?
There's multiple reasons. The single most important overall can be seen right at the end of the video; The system vectors are stored in 00FFE0 to 00FFFF This is the first thing the system checks when it first powers on, so if there's nothing stored there the system will fail to boot anything. However, for practical reasons, it's better if games map their code to the upper banks (banks 80 and above), since amongst other things, that may be able to run at higher speeds, and you won't have to deal with the System RAM eating some of the address space (ROM in the system RAM area is impossible to access) This shows our first issue; We want the ROM in the 80+ banks, but we NEED there to be valid data for the system vectors in the upper end of Bank 00 The easiest solution to this is mirroring. The second reason, which is why there's that weird scheme where some of the quadrants only allow ROM in the upper half, is that the 65816 is a 16 bit CPU, but 16 megabytes of address space is 24 bits; One of the consequences of this is that you can access a 64 kilobyte 'page' somewhat faster than trying to access any arbitrary address in the 16 megabyte range. This also means that, where possible you should try and keep everything you're currently working with in the same bank (eg. same 64k region) If you're only dealing with ROM, use a bank that only has ROM mapped in it; But if you need some RAM, then it's helpful to have some RAM in the same bank. And similarly if you're working with the PPU registers (which you will be in many cases), it's helpful to have all of those in the same bank as well. This is why not only are there banks where the lower half contains a small part of the system RAM, but also all the control registers for the hardware. And, why that small chunk of RAM and those control registers are deliberately mirrored across so many banks; So that no matter which of these banks you're dealing with, they'll always be accessible. Some other things include that: - it's slightly safer for programmers if most areas of the memory map contain some kind of valid data, even if that's a copy of something else, because reading from an area that has no hardware at all attached to it would mean reading from 'open bus', which causes weird, unpredictable behaviour; For well-written code, this won't matter because you won't access 'forbidden' areas, but for mildly buggy mode this makes it marginally less likely the system will randomly crash - Mirroring is actually easier to implement in hardware than NOT mirroring; To understand why you kind of need to understand how the actual electronics work to at least a limited extent. When you read/write from a memory address, what the CPU actually does is set a value on the address bus, tell the attached devices whether it intends to read or write from the address, then read or write the value from the data bus. However, physically, with a 16 megabyte address space this actually means there are 24 physical lines (electrical pathways) for the address bus, and 8 more for the data bus. Let's say you want to map 1 megabyte of ROM into this somehow. You wire up the 8 pins of the data bus, wire the read/write pins, and if required, a chip select pin. (this turns entire memory chips on and off; not super important when there's only one memory chip, but if there's more than one, you only want a single one to respond at the same time). But then you wire up the address pins. - except 1 megabyte only requires 20 pins (2^20 bytes = 1 megabyte), and you have 24! What happens to those 4 pins you didn't connect? Well, it turns out you can ignore them; If they're not connected to anything, when a value is written to that pin, nothing happens. But, think about what this means; You've just wired up a chip such that 20 pins select an address in your ROM chip, and the remaining 4 are ignored. But, what happens if you change the value on one of the ignored pins, but also change the value on one of the pins that's wired up? Well, sine those 4 leftover pins get ignored entirely, the actual effect is that the ROM chip still responds anyway and puts data on the bus. What data? The exact same data whatever matches the 20 pins that are already connected! So, what does this do? Well, if you hadn't guessed already, this causes the data to be mirrored at multiple addresses. And to AVOID mirroring actually requires that you attach something to these remaining 4 pins and use some kind of logic circuit to make sure that the ROM chip doesn't respond if any of those extra address pins are active. In other words, NOT mirroring requires extra circuitry vs simply letting the data be mirrored. So... Mirroring is the less complex thing to implement, thus unless there's some practical reason why having mirroring will mess up your system, you basically always end up with mirroring, since disabling it takes extra work for no good reason. As to what is mirrored? Well, that depends on how you connect your pins. You might at first glance think... We have 20 pins so we ignore the 4 highest ones, right? Well, that IS one option. But think about what removing each pin actually does; If you number the pins 0 to 23 (by convention this kind of thing usually starts with a pin 0, not pin 1), then disabling the top 4 pins (pins 19-23) causes mirroring every 16 banks. (there are 256 banks total because a 'bank' refers to the upper 8 bits of a 24 bit address) That is, bank 0 is mirrored into bank 16, 32, 48, 64 and so on, and bank 1 is mapped to 17,33,49 etc... Nothing wrong with that, but what about other options? Well, mirroring the upper and lower half of memory results from ignoring pin 23 And what about this weird thing where for each bank the lower 32 kilobytes matches the upper 32 kilobytes? Well, if you think this through, this results from skipping pin 15. So pins 0 to 14 on our hypothetical 1 megabyte ROM chip map to pins 0 to 14 of the address, but then pin 15 of the ROM chip maps to pin 16 of the address, and everything else continues from there (17 to 16, 18 to 17, etc) The reasons for choosing any particular type of mirroring relate to what you wish to accomplish, but the general idea of mirroring actually results because it's the easier thing to implement than creating the circuitry required to avoid mirroring from happening. And if you're wondering why they'd want to do that weird 32k mirror specifically... Think about really small games; (there are other reasons, but this is the most immediately obvious) Let's say your entire game is 32k total; The most obvious thing to do would be to map that in bank 0, from 0000 to 7FFF, which is the first 32k of memory. But, all of our hardware registers are in this bank, and so is the first 8k of our RAM, since we decided it'd be useful to have this easily accessible without always needing to change banks to get at it. So our 32k is actually not fully accessible if we put it here. More significantly, we need the ROM to contain our system vectors, which, as I noted way back, are in the FE00 to FFFF memory region. So our naive idea of mapping our ROM into the first 32k actually won't even boot. So, what then? Well, luckily, if we simply don't connect any pins above pin 14, we naturally get this 32k mirrored into the upper half of bank 0, and suddenly everything works flawlessly. But if we happen to have more than 64k, we get an extra benefit from continuing to skip address pin 15 anyway; Our entire ROM, as long as it's small enough (less than about 8 megabytes) can map into the upper 32 regions of each bank, and, aside from the banks that contain our 128k of RAM, nothing in ROM will interfere with the hardware registers for any reason. I could go on with other details, but I think you probably get the general idea by now; Mirroring (and specifically deciding which parts of memory to mirror) is used to solve various minor technical issues, but overall the real reason why mirroring exists at all is because the simplest hardware solution for using less than the full 16 megabyte address space (or any situation in which a computer has more address space than physical memory), automatically leads to mirroring, and it's actually more difficult and expensive to avoid mirroring than to just let it happen.
@@KuraIthys I think you should help write for the show! But in all seriousness, I was wondering the same thing and after reading your comment, it makes a lot of sense now from both a hardware and a software point of view. I was thinking it was only meant to help the software end as a quick access point for any data.
Thank you. I think the show is doing pretty well without my help though. XD But it's always nice to hear that someone appreciates an explanation like that. Mirroring is one of those things that just seems really weird at first glance, but actually has a lot of good reasons to exist. (and in fact exists be default in a memory system unless you actively work to avoid it.)
Can you explain why the memory map is conventionally flipped? I can't find any reasoning for it when I search but I might not be using the right terms in my search. I'm hoping there's more to it than "This is how it's always been done."
The memory map provided by Nintendo in their official developer's manual is in this orientation, and I guess every variation of it since then has just stuck to that orientation.
Memory allocation: - 1st group 8-bit: cells - 2nd group 8-bit: pages - 3rd group 8-bit: banks - 4th group 8-bit: ??? What next names group 8-bit ? (else memory bigger 16MB)
Going from the VIC 20 memory map to this was not a good idea, it was enjoyable tho. not even planning to learn assembler, just wanna know more or less the ins and outs of 8 and 16 bit machines.
I might of missed this but where can you write to memory? like where is mario's lives/coins stored? everything seems to already be taken by mirrors or open bus space.
I wasn't able to follow about 90% of that, but I'd be willing to learn more so I can understand it. With each video, my respect for the programmers of the time grows.
Please do a supplemental explanation for the Super Metroid/Link to the Past crossover randomiser so there's a decent explanation for linking literally anywhere.
Hard to tell. There's only one "accessible" copy of the hardware in existence, its specs aren't well known, and when they attempted homebrew on it it wouldn't run without severe glitches due to... the SNES CD (Sony) adding new, completely unknown hardware interrupts.
I haven't finished the video but is there really nothing that uses the space between JOY and PPU? Edit: oh I see, other chips can use it. Still feels strange.
You can with irq, but in order to change ppu registers, you must turn off the beam, thus small black horizontal line. Also you don't have plenty of time. You can do perhaps one or two ppu changes between a horizontal line.
I mean, you can even adjust sPPU registers during active display and they work, just with a couple glitch pixels where the write occurs, but doing it during H-blank works perfectly without glitches. Anybody who thinks it can't because of the CPU speed, hasn't pulled out a calculator.
@@aaendi6661 You can't update palette in mid-horizontal line without f-blank (you will have black line). Nor S-PPU (21XX) registers. Source: wiki.superfamicom.org/registers
I have to wonder why there was never a MidROM configuration that uses the entire ROMSEL region to it's fullest. You always lose 2MB of addressing space in either configuration. (4MB for the Ex**ROM variants)
@@aaendi6661 Only if you used ExMidROM. And that's not really the point: the point is to avoid messing around with bank switching or stranding half your game in slow ROM mode. If you want >4MB in your ROM, you have to either use bank switching, or the slow ROM mirror space. Both are a pain in different ways, when you could get an extra 2MB "for free" by using ROMSEL space more efficiently.
LoROM feels so unintuitive on a 16 bit system, have your ROM split up in 32 kByte pages. All just because the ghost of the NES haunts the SNES. I wonder how far the backwards compatibility goes and what games might run unmodified.
So, are you saying the SNES is actually a 24-bit console with a 15-bit graphics card? You heard right, 15-bit. Because it can only choose from roughly 33,000 colors. 16-bit would by over 65,000 colors. Although I bet the video card itself does have a 16-bit wide data bus.
Only the addressing is 24-bit but the SNES uses otherwise a 16-bit processor (65c816), though with an 8-bit bus. That the SNES uses 15-bits for its colour is only done to make each colour uniform as using all 16-bits means one colour can display more colours (and besides, the single bit won't make any major visual difference anyway), not to mention that the fixed colour (read: background colour) needs to be adjusted too (each primary colour in the fixed colour uses the same register: 5 bits are used for the colour value itself whereas bits 5 to 7 determine which colours to write to).
@@vytah My understanding, CPUs bit sizing is based on it's memory allocation. 32-bit means it can allocate up to 32-bit amount of memory. Same as 64-bit. 64-bit addressing of memory. MS-DOS, Windows, Linux, etc are Operating System. Not CPUs.
@@baddmatt9588 Intel x64 supports up to 48 bits (currently) of virtual address bits and my particular CPU claims to have 39 physical lines. So is my CPU 39-bit, 48-bit? Of course not. Though I'm not sure if the pointer size (64 bits) is what gave it its name of 64-bit. The thing is, the bitness of each CPU is decided by convention and stuff such as address size, general purpose register size etc are mere heuristics. By the heuristic of general purpose registers, the Intel CPU in my laptop, the ARM (Cortex A53) CPUs in my phone and my RPI are 64-bit and the Intel 8086 is a 16-bit (with 20-bit addresses). The 65816 in the SNES is 16-bit due to its 16-bit registers (though it is claimed to be 8/16 bit due to the selectability between 8-bit and 16-bit registers; that's just another oddity in the naming, but they wanted to market that selectability so this stuck), while the 6502 is a definitely 8-bit CPU even though the address space is 16-bit. Look at the general purpose registers. Not address sizes, not other heuristics. The size of the general purpose registers determine the bitness of a CPU. If you look at the largest register, my CPU would be 512-bit due to the AVX registers. Old 32-bit-only Intel CPUs would be 80-bit because their FPU (which is inside the CPU since the '486) works with 80-bit floating point values (which some C compilers expose as "long double"). Of course that isn't a good heuristic!
Wait, what!? 6502 emulation mode? I never heard about that before. You mean there's a way to execute 6502 assembly in the SNES CPU? What else is compatible with the NES? Not much I assume, otherwise we would have seen retrocompatibility back then. But I guess that explains some ports that are way too close to their NES counterparts, like Ninja Gaiden Trilogy. At least the logic could be ported, right?
Yes, it's a standard feature of the 65816. Almost all SNES games switch to native mode almost immediately on boot though. The 65816 instruction set is a strict superset of the 6502's (as long as you don't rely on the "illegal" opcodes of the latter.) This similarity would generally have made it very easy to port NES code to the SNES. I imagine Super Mario All-Stars made good use of this. Has anyone actually checked? How much code in SMAS is copied verbatim from the original NES games?
@@0x5D That's amazing. Unlike Sega, Nintendo wasn't very famous for retrocompatibility at the time and I don't remember ever reading about this before, but yet... It was there all the time. Now I'm also curious about SMAS.
obligatory pedantic comment that kilobytes (kB, 1000 bytes) are not the same thing as kibibytes (kiB, 1024 bytes), and megabytes (MB, 1000000 bytes) are not the same as mebibytes (MiB, 1048576 bytes)
person one: "press 'F' to pay respects" person two: "you know there are 16 people here right?" person one: "oh, fork, now these 'F's are making hex 'FFFF FFFF FFFF FFFF' so now it's equal to -1"
It's crazy how such an obtuse and unintuitive subject can become simple and clear through just proper explanations and simple diagrams.
Thank you for your work.
@@B3Band ive been reading up on assembly for the snes, and this makes it so much more clear.
programming, in general has that reputation because people just don't explain it properly...
assembly and other low-level cocepts tend to have it worse since they're considered "obsolete" in most applications [till you mess with drivers, compilers, NEW systems, embedded systems, so on]
i'm personally starting to see assembly and whatnot as being positively more SANE than C++ and its derivatives..
they still can be hard without the right sources of documentation, but the only real difference is there's a lot of manual memory management, and it takes many small steps to do something that seems 'simple' in other languages. i admit it's scary that you could so easily cause a fatal exception and totally crash the machine, but i somewhat prefer that over the abstractions and crap built-into C++ and the likes
not sure if i'll ever touch SNES homebrew or hacking, but this is an awesome series, and i do find it quite interesting actually being able to LEARN how this stuff works. One of the big turn-offs for me is that finding good documentation is next to IMPOSSIBLE. [btw, don't lookup windows exes...]
i've currently been looking into 68k assembly and trying to reverse-engineer a NEO-GEO game. that's... umm...interesting. So far, documentation on the system is pretty good. My gripe is the CPU... I have currently three major sources of documentation I'm using, all for specific purposes... >.> [Which is why I have not touched this particular project for months until now.] Ofc, the M68K is actually a fairly complicated processor, but it certainly isn't as bad as x86! I'm slowly starting to grasp it better. At least there was thought into what kinds of complicated instructions were really necessary. One of my least favorite x86 things to actually try and understand is/was "repeat not equal scan a string of bytes" aka repne scasb. I kinda get it now, but not personally one of my favorite opcodes to stumble upon... It's one thing to say "this is how you get the length of a string" [its main use]. It's another to break it down and EXPLAIN what, exactly it's doing...
I have a few windows games I'm looking at, but I'm a bit burnt-out from the combination of x86's nightmare fuel instruction set and the way windows executable files work behind the scenes. It's just not fun... Good news is what I was doing this for was mainly to break-apart resource files, which I'm slowly figuring-out on my own. [and with some help] I could probably code the logic for one of these games by myself, now. The others might require some research, but it's certainly faster than slowly working-through assembly code.
Anyways, the content on this channel is pretty top-notch. The world needs more like it. Maybe assembly wouldn't scare people so much, and maybe homebrew development and/or ROMhacking would be more accessible, if the resources were actually OUT there to explain it in a manner that's easy to digest. So far, they're quite lacking...
I know assembly used to completely terrify me. And then I discovered the small handful of places that explain it in a way that it may be understood. [from my experience, it's usually not those technical manuals] I'm nowhere in a position to be completely proficient with it, or make use of it, but I'm learning, slowly. It's overall a pretty fun process. It can be stressful or frustrating, but it's exciting to learn about, especially actually be able to understand even a fraction of just how our computers manage all the complexity that most of us would take for granted.
What about C, it's supposed to be closer to the 'metal' than C++?
@@B3Band He meant simple as in "easy to read", not "easy to make".
Oh boy, next one is going to be about the SPC-700. I've been anticipating that one.
Tails19935 The last three are the ones that interest me the most.
Yep
Yes, but actually no. The audio videos are going to be split. The next one will just be about how it interfaces with the rest of the system. Or so I hear.
@@henke37 If that is the case then I can understand why. Like how the Super FX chip and other peripherals are going to be covered in a sperate video as mentioned in this one.
To which I'll do the same as I've been doing. Waiting patiently while also enjoying any other content that comes down the pipeline.
I can't wait either. This is an awesome series.
The more I watch this, the more i think, "wow the snes really is a super version of the NES"
It was originally meant to be backward compatible! But they couldn't make that work without being too expensive.
@@renakunisaki It's such a shame that they underclocked the CPU for that, but were too far along in development to reverse it when they cancelled the feature.
The Snes's CPU isn't even a problem. Everybody just programmed it the wrong way.
@@aaendi6661 Well, if the programming techniques known to the programmers at that time were completely unorthodox to how the CPU should be programmed, is it the designer's fault or the programmers' fault?
For me, particularly, the best thing they did on the GBA was putting an ARM processor.
@@JoaoBapt All they had to do was ditch the belief that "the more cycles you use the faster it runs."
With explanations like this, you could be a college professor of a SNES programming course
I would ABSOLUTELY take his course.
Now imagine, on NES you only have the first column of this graph, 0000-FFFF, so only 16-bit addresses. This 64kB area is then broken down similarly:
0000-07FF - 2kB Work RAM
0800-1FFF - Mirrors of Work RAM
2000-2007 - PPU registers
2008-3FFF - Mirrors of PPU registers
4000-401F - APU (sound) & Joypad registers, Factory testing registers (locked without modding)
4020-7FFF - Not mapped / Open bus (typically used by extra Work or SRAM and more advanced MMC chips)
8000-FFF9 - Cartridge ROM (an MMC chip in the cart if any, is responsible for banking the larger ROM into this area)
FFFA-FFFF - Interrupt Vectors
The SNES was planned to be backwards compatible but that idea was canned half trough the project, too late to change stuff around tough.
One of my favorite channels on TH-cam. By far. Not only is the content niche and extremely interesting, but the delivery and presentation is absolutely exceptional. Keep it up!
Yay! More technical details about a system I'll never need to know about, but love learning about anyways!
Sounds like school, just remove the "love" part
Although, now that you do know a load of the technical details, why not do something with it just for fun? :-D
You also don't "need" to know about history, art, geography, and so on... After all, you just need to know how to open your mouth and throw pringles in there... You will go very far in life with such mindset. Let me guess, another millenial?
@@DrNoBrazil What about Math?
@@jl86_ Don't feed the trolls. He's wrong anyway. I prefer Funyuns.
oh, so that's why most action replay codes starts with 7E i wish i knew that back in the 90's
I remember realizing that AR and Game Shark codes were all just hex code injected into games. I knew much less about computers/programming then, but it was def a profound realization lol
I'm glad you explained *why* all the different mapping modes exist. It seemed unnecessarily complicated to me when I read it (compared to the Genesis, for example, where the map is almost always the same), but having different modes for different tradeoffs w.r.t. data contiguity and access time makes a lot more sense.
It's too bad 99% ended up just using long addressing for everything in SNES, throwing any speed benefit from the way nintendo organized memory out the window.
@@aaendi6661 I'm very interested into which games actually used the SNES the best way possible, do you have examples?
*FOR THOSE ASKING ABOUT 'WHY MIRROR RAM'*
From what I got (I'm no expert, but I have at least some understanding of memory and programming) .... picture a Playstation Game on 4 discs. Say, FF8. As you go through the game, you can revisit older areas. Why? Because those older areas' data are mirrored on the later discs. If they didn't mirror the older areas' data, then you would get a "Please Insert Disc 1" every time you wanted to step into Balamb Garden, for example. The memory mapping works much the same way: If you're working in a specific area of the RAM, it is much slower to jump out of that section, and into another section to find the data you need. UNLESS, of course, you copied that data and mirrored it into several different sections. Now, they didn't mirror ALL of the data, only some of it, just like in FF8 .... dialogue and cutscenes, for example, the FMV video that plays during the assault at the beginning of the game only exists on Disc1, as does the FMVs where Squall is dancing with Rinoa. Why? Because you'll never see that cutscene past that point in the game, no point in copying that onto the other discs. But, Balamb Garden's assets need to be copied onto 3 of the discs, because it is possible to visit Balamb Garden at multiple points in the game. You don't want the player switching discs constantly, so you copy some of those assets that you think the player will be needing periodically throughout the game. Make more sense?
But the whole point of RAM is that it allows random access... I'm not sure what it means to "jump out of" a section of RAM, I'm not sure that makes sense. Are we talking about caching, or segment registers, or what?
@@thealliedhacker If you saw earlier in the video, you address different parts of RAM with addresses. $AABBCC format where AA is the pointer to what section of RAM you're working in. Let's say there's an address that you need some data from at, say, 01AAAA. You could just simply write "AAAA" (which saves you 2 letters in the code) and if you're already working in area 01XXXX, the 01 is implied unless specified otherwise. But what happens if you're working in area 07XXXX and you need the data that's stored at 01AAAA? You'd have to code your instruction to specify 01AAAA every time you want to point to that data. Unless of course that 07AAAA is mirrored and is the same as 01AAAA. Then you could, in fact, just write AAAA and you'd get the same data (you'd be jumping to 07AAAA but that's fine, because 07AAAA has the same data as 01AAAA).
EDIT: Also, correct me if I'm wrong, but if you're working in area 07XXXX and you specify that you wanna go to 01AAAA for data, doesn't the implied area change to 01 so you'd have to again change it back to 07 to return to area 07?
@@Dhalin Well, that just sounds like we're trying to save memory by reducing the size of the instruction, not that the instruction will actually take longer to execute. It still seems like the speed is the same, unless decoding the longer instruction is slower or switching the bank has its own intrinsic cost for some reason...
@@thealliedhacker Well, if my edit is true, then it would also take extra instruction time to swap whatever the "current" area of RAM is, too. There's probably more to it, in the actual circuitry, a millisecond here, a millisecond there, I mean, a lot of SNES games lag as it is when there's too much going on, so I'm sure they did these things for a valid reason.
@@Dhalin Well, I assume it wouldn't require an extra instruction to move back though, since the next instruction could also just use an extended address, so we still wouldn't lose any time...? I dunno, maybe the main factor is just saving the space in the instructions.
8 AM and an RGME video.
Today's going to be a good day.
I have a hard time entirely understanding these videos, but in every one I learn a little bit something new about the wonderful SNES. Keep up the good work.
Underrated creator. Keep it up bud, hope you hit 1M soon.
I love this series, it's super interesting, very well written and comprehensive. Thank you RGM, very cool.
Excellent presentation as always. Memory mapping becomes intuitive with nice graphics!
Brilliant stuff. Hoping for Mega Drive, PC Engine, Neo-Geo in the future. Good to know how my favorite stuff work.
next one will be the one we've been waiting in years
I'm the most hardcore kind of gaming nerd and I didn't realize until I read out this comment from Tails19935: "Oh boy, next one is going to be about the SPC-700. I've been anticipating that one."
This goes straight above my head. (I still love watching it.)
I just found this comment and by now I just about understand the video.
These are some of my favorite videos on TH-cam. Amazing work!
The funny thing is that, Nintendo spent all this effort designing the memory map so programmers could use 16-bit addressing mode, yet 99% of programmers went with long addressimg mode for everything anyway.
what... but that's a huge hit on performance on an already underclocked CPU... It really should've run at 7.12Mhz, like the Turbografx
@@vuurniacsquarewave5091 The reason why everybody did it like that was because Konami did it that way, and everybody just took Konami's word for it.
Turns out developer time is a finite ressource too, and more costly than hardware.
Also, hardware designers have a very bad habit of poor documentation. I do remember many early SNES games lagged unnecessarily because of this.
I’m not even gonna pretend I can understand everything you’re talking about, but I still can’t get enough of your videos. You are too good! Keep it up.
Thank you so much for explaining the memory mapping! That was the confusing part of most of your prior videos having to do with RAM.
I love your video style! It's great for listening to when I'm working on things, I've already seen every video at least 3 times so far.
Yay! Love this series, you have a way of explaining all these concepts and make them so easier to grasp :D
Hella cool as always!
I love learning about how the old tech worked, and you teach it well!
Thank you! I have wondered about this for some time.
One thing to add is that the cpu can have 24 bit instructions. But works faster if you restrict yourself to instructions using only 16 or 8 bit addresses. This makes it useful to layout the memory in such a complicated way
Too bad nobody took advantage of this.
@@aaendi6661 I'm sure you're exaggerating a bit... Then again, I don't know too much of the SNES outside of SMW and YI.
@@MarioFanGamer659 I don't know about Yoshi's Island, but Super Mario World definitely overuses long addressing.
@@aaendi6661 I get your point but also remember that SMW is a launch game (it also was slightly rushed, IIRC) and the 65c816 processor is a rarely used processor it makes sense why it used unnecessarily long addressing (at least the lack of data bank shenanigans). Of course, it also uses (sometimes) long addressing when it isn't absolutely necessary (either same data bank or data bank switch is faster) which is where I get the "overused" part (I still believe you make mountains out of molehills, though).
@@MarioFanGamer659 Capcom never got any better with it.
my happiness levels have gone to maximum. and on my birthday, now thats epic
You are a legend. Everything so far is crystal clear. I can't wait for the SPC 700 video.
Yes, I've been waiting for this! Nice video, it really taught me alot!
An unexpected windfall after a long day at work, time to kick back and nerd out =)
Thank you, great video. This is the part of the SNES that I've really wanted a good explanation for.
I wish there was some quiz or something so I could make sure I'm properly digesting this information properly
I always go back to older videos to remember a few things. This one is pretty self contained though.
Imagine if Nintendo had actually gone through with full NES backwards compatibility. I wonder how they would've implemented the audio in that case.
I actually wish the SNES had NES audio as well as a couple extra channels. The SPC700 is frustrating as hell to work with.
Emulation?
@@aaendi6661is it possible to make some kind of expansion like the Super Game Boy but for NES games? There would be a NES CPU, PPU, and RAM (somehow condensed idk) as well as a NES cartridge port. I wonder if the NES APU could be played alongside the SPC700. Not sure how the Super Game Boy does it (if it even includes the LR35902 sound at all, I should've searched this up before writing)
Can’t wait for that sound department because it’s a really interesting subject to discuse about it.
God, your diagram game is SO damn good. Jesus man.
Such an interesting video! Love your channel, keep it up :D
hell yes, finally more of this, cant wait for the last two
I'm soooooooo excited for the next video!!! Always amazing and detailed content!
*watches video about an interesting topic*
i am bored
*sees this*
OH BOY
Can't wait for the SPC700 video.
Fantastic work on this!!
Yeeeeeeeeeaaaaaaahhhhhhh! More technical-ness! Btw, do you think you will do the Sega Genesis after the SNES? I was just wondering bc I am intrigued about it.
Sega Saturn would be even more interesting IMO.
@@Redhotsmasher Saturn does sound interesting...
@@Redhotsmasher With how complex it is to program on it (from what I've heard at least), it definitely sounds interesting.
Almost at 100,000 subs LETS GO
Some Game Boy games might have had those null buffers too. I always wonder if they contain anything interesting. Even a ROM dump usually won't include them, unless it's done by extracting the actual chip.
(The GB games would be any that use MBC1 chip with more than 1MB of ROM. But I'm not sure any exist... 😅)
I can't wait until 2020 when you will cover the S-DSP and SPC700 and we will see the true extent of pitch modulation, white noise, the delay module, and what's up with that BRR compression.
Were you even alive when the SNES was popular? Great video!
Woo! 100,010 subs! Congrats!
emulation mode and a bunch of stuff meant to be backwards compatible with the NES... interesting...
"If it ain't broke don't fix it"
Which was never actually put into good usage.
3:04 - "Retro Game Machanics says FF FF for 1 hour" when? :P
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
"F" to pay respects.
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
Me and the bois learning about memory mapping
And I'm not even into SNes programming. But this is presented perfectly, respect!
Only 800 subs to 💯 k! But you really deserve it!
Commander Red 🙌🏼 🎊
The more I learn, the more respect I have for Nintendo for sneaking all these workarounds in. They knew they effed up with their choice of a CPU (and their orphaned NES legacy), but they crammed in all the secret features they could to compensate. And when a developer actually USES them? The system punches well above its weight.
Objects in address space may be smaller than they appear
I still dont get why the Address space wastes so many addresses on mirroring why mirror if the entire 24bit space is addressable? is it to save clock ticks on higher address access? Just dont get the logic.
Incomplete decoding of addresses was a common trick to save transistors back then. The decoder circuit would only check the n highest or lowest bits of the address instead of checking every bit. Often, e.g. with smaller ROM chips, the excess high address lines were just ignored, which resulted in ROM mirroring over the CPU address space.
And not many games used the entire ~8 MB theoretical ROM capacity of an un-switched SNES cart. They only started pushing this towards the very end of the SNES's lifespan. Super Mario World was only 512 KB.
Great stuff, as always.
** Replaces every university professor where it costs $50k/yr with this guy's TH-cam channel **
... so all of these mirrors are so if you're on a particular vertical line/bank, what you can access from there without changing banks?
For the RAM mirroring, yes. The 65816 instruction set was such that accessing data in the one "current" bank was 1 or 2 cycles faster, and took one less byte, than specifying a full 24 bit address. And the only way to change banks was with stack instructions (PHB,PLB,etc.) which were 3 or 4 cycles a pop (or push, hehe). Obviously this won't do during vblank, when you're in a tight race to get everything to the PPU for the next frame. So the solution was to have a small part of WRAM always visible in the same bank with all the I/O registers, so that if you structured your game's memory properly you wouldn't have to change banks often.
ROM mirroring was mostly just because the ROM chips in smaller games didn't use all the available address lines. They only used the n lowest bits of the address and ignored the rest.
@@0x5D so, basically, it's a bit like trying to use on CPU RAM for as much as possible.
16:46 - 16:49
I’ve heard about misunderstandings concerning hexadecimal but this is rediculous
Holy fuck that is funny xD
LOL
after watching this vid i have more questions, then answers. And these questions are new ones.
The LoROM seems similar to how memory mapping worked on the NES. If the program bank register is between $80 and $BF, the data bank register set to $80, and the direct page is set to $8000, the memory is almost laid out the same as the NES.
When you write an instruction like STA 21 00, how do you know which page or what the actual address is?
The 65c816 CPU inside the SNES has 3 extra registers for program and memory access: the Direct Page Register, Program Bank Register, and the Data Bank Register. Your question pertains to the Data Bank Register.
The _DBR_ is an 8-bit register that specifies which bank data is accessed from when using a 16-bit addressing mode. So if the DBR has a value of $81, the instruction `LDA $2100` will access memory address $812100 . In short, the DBR acts as the high byte of the 24-bit address when a 16-bit addressing mode is used.
Similarly, when using an 8-bit addressing mode, the _Direct Page Register_ is used. This register is 16-bit, so if the Direct Page register has a value of $7E00, the instruction `LDA $2D` will access address $7E002D.
@@haruki_nyan Except direct page doesn't represent the high and bank bytes but rather, it is the base address and the address on the opcode is an index to that base address with $00 as the bank. Sounds complicated but it's really just addr + DP on bank $00 so $7E00 on $2D actually results in $007E2D (usually not mapped to anything) instead of $7E002D. And if DP were, $00D3, you get $000100 on `LDA $2D`.
God it's so dry. *I love it!*
All this block mirroring stuff makes me wonder if there is something going on that I don't know about. For example, is using a 24-bit address sufficiently burdensome that trying to use a 16-bit address within the same bank is preferable? Besides the obvious fact that 24-bit memory instructions are 32-bits in size, and the difficulty of assembling a 24-bit address from two registers.
That's the only reason I can come up with for why mirroring would be so frequently used, when you could just have more available storage in the ROM.
As you'll see in the followup to this video, mirroring is just a side effect of the simplest and easiest way of interfacing with memory chips.
What does the low and high refer to when talking about the different rom layouts? 🤔
This is super interesting and really helps me understand how mashups like Zelda/Metroid randomize works. One question for you: I thought Star Ocean used ExLoROM but you said it was never used by official games. What Map does Star Ocean use?
Thanks again! I love the series!
Well, if the game is bigger than 6MB, and if ExLoROM wasn't used commercially, then the only other choice would be ExHiROM. That, or they did some bank-switching magic like they used to do in the AT2600 days. I dunno if that's possible on a SNES or not, so just throwing theories out there?
Why the data is mirrored? what is the use of that copy?
To avoid having to switch banks as often I guess?
@@PhaaxGames Thanks!
There's multiple reasons.
The single most important overall can be seen right at the end of the video;
The system vectors are stored in 00FFE0 to 00FFFF
This is the first thing the system checks when it first powers on, so if there's nothing stored there the system will fail to boot anything.
However, for practical reasons, it's better if games map their code to the upper banks (banks 80 and above), since amongst other things, that may be able to run at higher speeds, and you won't have to deal with the System RAM eating some of the address space (ROM in the system RAM area is impossible to access)
This shows our first issue; We want the ROM in the 80+ banks, but we NEED there to be valid data for the system vectors in the upper end of Bank 00
The easiest solution to this is mirroring.
The second reason, which is why there's that weird scheme where some of the quadrants only allow ROM in the upper half, is that the 65816 is a 16 bit CPU, but 16 megabytes of address space is 24 bits;
One of the consequences of this is that you can access a 64 kilobyte 'page' somewhat faster than trying to access any arbitrary address in the 16 megabyte range.
This also means that, where possible you should try and keep everything you're currently working with in the same bank (eg. same 64k region)
If you're only dealing with ROM, use a bank that only has ROM mapped in it;
But if you need some RAM, then it's helpful to have some RAM in the same bank. And similarly if you're working with the PPU registers (which you will be in many cases), it's helpful to have all of those in the same bank as well.
This is why not only are there banks where the lower half contains a small part of the system RAM, but also all the control registers for the hardware.
And, why that small chunk of RAM and those control registers are deliberately mirrored across so many banks; So that no matter which of these banks you're dealing with, they'll always be accessible.
Some other things include that:
- it's slightly safer for programmers if most areas of the memory map contain some kind of valid data, even if that's a copy of something else, because reading from an area that has no hardware at all attached to it would mean reading from 'open bus', which causes weird, unpredictable behaviour; For well-written code, this won't matter because you won't access 'forbidden' areas, but for mildly buggy mode this makes it marginally less likely the system will randomly crash
- Mirroring is actually easier to implement in hardware than NOT mirroring;
To understand why you kind of need to understand how the actual electronics work to at least a limited extent.
When you read/write from a memory address, what the CPU actually does is set a value on the address bus, tell the attached devices whether it intends to read or write from the address, then read or write the value from the data bus.
However, physically, with a 16 megabyte address space this actually means there are 24 physical lines (electrical pathways) for the address bus, and 8 more for the data bus.
Let's say you want to map 1 megabyte of ROM into this somehow. You wire up the 8 pins of the data bus, wire the read/write pins, and if required, a chip select pin. (this turns entire memory chips on and off; not super important when there's only one memory chip, but if there's more than one, you only want a single one to respond at the same time). But then you wire up the address pins. - except 1 megabyte only requires 20 pins (2^20 bytes = 1 megabyte), and you have 24! What happens to those 4 pins you didn't connect?
Well, it turns out you can ignore them; If they're not connected to anything, when a value is written to that pin, nothing happens.
But, think about what this means; You've just wired up a chip such that 20 pins select an address in your ROM chip, and the remaining 4 are ignored.
But, what happens if you change the value on one of the ignored pins, but also change the value on one of the pins that's wired up?
Well, sine those 4 leftover pins get ignored entirely, the actual effect is that the ROM chip still responds anyway and puts data on the bus. What data? The exact same data whatever matches the 20 pins that are already connected!
So, what does this do? Well, if you hadn't guessed already, this causes the data to be mirrored at multiple addresses.
And to AVOID mirroring actually requires that you attach something to these remaining 4 pins and use some kind of logic circuit to make sure that the ROM chip doesn't respond if any of those extra address pins are active.
In other words, NOT mirroring requires extra circuitry vs simply letting the data be mirrored.
So... Mirroring is the less complex thing to implement, thus unless there's some practical reason why having mirroring will mess up your system, you basically always end up with mirroring, since disabling it takes extra work for no good reason.
As to what is mirrored? Well, that depends on how you connect your pins.
You might at first glance think... We have 20 pins so we ignore the 4 highest ones, right? Well, that IS one option.
But think about what removing each pin actually does; If you number the pins 0 to 23 (by convention this kind of thing usually starts with a pin 0, not pin 1), then disabling the top 4 pins (pins 19-23) causes mirroring every 16 banks. (there are 256 banks total because a 'bank' refers to the upper 8 bits of a 24 bit address)
That is, bank 0 is mirrored into bank 16, 32, 48, 64 and so on, and bank 1 is mapped to 17,33,49 etc...
Nothing wrong with that, but what about other options? Well, mirroring the upper and lower half of memory results from ignoring pin 23
And what about this weird thing where for each bank the lower 32 kilobytes matches the upper 32 kilobytes?
Well, if you think this through, this results from skipping pin 15.
So pins 0 to 14 on our hypothetical 1 megabyte ROM chip map to pins 0 to 14 of the address, but then pin 15 of the ROM chip maps to pin 16 of the address, and everything else continues from there (17 to 16, 18 to 17, etc)
The reasons for choosing any particular type of mirroring relate to what you wish to accomplish, but the general idea of mirroring actually results because it's the easier thing to implement than creating the circuitry required to avoid mirroring from happening.
And if you're wondering why they'd want to do that weird 32k mirror specifically... Think about really small games; (there are other reasons, but this is the most immediately obvious)
Let's say your entire game is 32k total;
The most obvious thing to do would be to map that in bank 0, from 0000 to 7FFF, which is the first 32k of memory.
But, all of our hardware registers are in this bank, and so is the first 8k of our RAM, since we decided it'd be useful to have this easily accessible without always needing to change banks to get at it.
So our 32k is actually not fully accessible if we put it here.
More significantly, we need the ROM to contain our system vectors, which, as I noted way back, are in the FE00 to FFFF memory region.
So our naive idea of mapping our ROM into the first 32k actually won't even boot.
So, what then? Well, luckily, if we simply don't connect any pins above pin 14, we naturally get this 32k mirrored into the upper half of bank 0, and suddenly everything works flawlessly.
But if we happen to have more than 64k, we get an extra benefit from continuing to skip address pin 15 anyway; Our entire ROM, as long as it's small enough (less than about 8 megabytes) can map into the upper 32 regions of each bank, and, aside from the banks that contain our 128k of RAM, nothing in ROM will interfere with the hardware registers for any reason.
I could go on with other details, but I think you probably get the general idea by now;
Mirroring (and specifically deciding which parts of memory to mirror) is used to solve various minor technical issues, but overall the real reason why mirroring exists at all is because the simplest hardware solution for using less than the full 16 megabyte address space (or any situation in which a computer has more address space than physical memory), automatically leads to mirroring, and it's actually more difficult and expensive to avoid mirroring than to just let it happen.
@@KuraIthys I think you should help write for the show! But in all seriousness, I was wondering the same thing and after reading your comment, it makes a lot of sense now from both a hardware and a software point of view. I was thinking it was only meant to help the software end as a quick access point for any data.
Thank you. I think the show is doing pretty well without my help though. XD
But it's always nice to hear that someone appreciates an explanation like that.
Mirroring is one of those things that just seems really weird at first glance, but actually has a lot of good reasons to exist. (and in fact exists be default in a memory system unless you actively work to avoid it.)
Do you still plan to do a video about the other mapper chips, or any of the add on chips mentioned?
I would like to, yes, but they aren't a priority at the moment.
please posess assembling a playlist of this series
16:38 Actually there's slightly more space because only the top half of WRAM is obstructing ROM, unlike in ExHiROM where all of WRAM is obstructing.
Can you explain why the memory map is conventionally flipped? I can't find any reasoning for it when I search but I might not be using the right terms in my search. I'm hoping there's more to it than "This is how it's always been done."
The memory map provided by Nintendo in their official developer's manual is in this orientation, and I guess every variation of it since then has just stuck to that orientation.
@@RGMechEx Thank you so much for solving that little mystery.
Memory allocation:
- 1st group 8-bit: cells
- 2nd group 8-bit: pages
- 3rd group 8-bit: banks
- 4th group 8-bit: ???
What next names group 8-bit ?
(else memory bigger 16MB)
On the way to 100k subs!
Going from the VIC 20 memory map to this was not a good idea, it was enjoyable tho.
not even planning to learn assembler, just wanna know more or less the ins and outs of 8 and 16 bit machines.
3:33 Nintendo reversed the memory addresses? The mental gymnastics of working in this memory map would drive me to an early grave.
So can the normal HIROM mapping only support 128 kB of cartridge SRAM (16 banks of 8 kB segments)? I thought it supported 256 kB?
I Love these vids
I might of missed this but where can you write to memory? like where is mario's lives/coins stored? everything seems to already be taken by mirrors or open bus space.
WRAM.
He mentioned that banks $7E and $7F are hardcoded to WRAM.
Patreon Notification Squad signing in
So fucking underrated
I wasn't able to follow about 90% of that, but I'd be willing to learn more so I can understand it. With each video, my respect for the programmers of the time grows.
Please do a supplemental explanation for the Super Metroid/Link to the Past crossover randomiser so there's a decent explanation for linking literally anywhere.
I think this series should have a video on how the (unreleased) SNES CD addon works as well.
Hard to tell. There's only one "accessible" copy of the hardware in existence, its specs aren't well known, and when they attempted homebrew on it it wouldn't run without severe glitches due to... the SNES CD (Sony) adding new, completely unknown hardware interrupts.
@@CarbuncleMotha9 I thought they got homebrew working properly in the end? Perhaps I'm mistaken.
Could you do a series about the Gameboy hardware?
Is that a Quadrant or a Quarter?
I haven't finished the video but is there really nothing that uses the space between JOY and PPU?
Edit: oh I see, other chips can use it. Still feels strange.
So, there's H-Blank DMA and V-Blank interrupts, but no H-Blank interrupts, so one can't do anything *too* crazy between lines?
You can with irq, but in order to change ppu registers, you must turn off the beam, thus small black horizontal line. Also you don't have plenty of time. You can do perhaps one or two ppu changes between a horizontal line.
@@gizaha Thanks.
No, it's only VRAM and OAM you can't change. S-PPU registers and palette can be updated anytime, they just cause a few glitch pixels.
I mean, you can even adjust sPPU registers during active display and they work, just with a couple glitch pixels where the write occurs, but doing it during H-blank works perfectly without glitches.
Anybody who thinks it can't because of the CPU speed, hasn't pulled out a calculator.
@@aaendi6661 You can't update palette in mid-horizontal line without f-blank (you will have black line). Nor S-PPU (21XX) registers. Source: wiki.superfamicom.org/registers
Banks wants to empty the banks, fill our streets with banks, and run a bank making operation out of his banks.
I have to wonder why there was never a MidROM configuration that uses the entire ROMSEL region to it's fullest. You always lose 2MB of addressing space in either configuration. (4MB for the Ex**ROM variants)
You mean a massive 95 megabit game?
@@aaendi6661 Only if you used ExMidROM. And that's not really the point: the point is to avoid messing around with bank switching or stranding half your game in slow ROM mode.
If you want >4MB in your ROM, you have to either use bank switching, or the slow ROM mirror space. Both are a pain in different ways, when you could get an extra 2MB "for free" by using ROMSEL space more efficiently.
Did anything actually USE the 6502 emulation mode on the SNES???
Your good at this, try the N64: Super Mario 64 Stair Glitch Explained
You mean the Backwards Long Jump?
That is a cozy graph
LoROM feels so unintuitive on a 16 bit system, have your ROM split up in 32 kByte pages. All just because the ghost of the NES haunts the SNES. I wonder how far the backwards compatibility goes and what games might run unmodified.
So, are you saying the SNES is actually a 24-bit console with a 15-bit graphics card? You heard right, 15-bit. Because it can only choose from roughly 33,000 colors. 16-bit would by over 65,000 colors. Although I bet the video card itself does have a 16-bit wide data bus.
It's considered 16 bit because that's the size of its CPU registers. Similarly the N64 only has a 32-bit bus.
Only the addressing is 24-bit but the SNES uses otherwise a 16-bit processor (65c816), though with an 8-bit bus. That the SNES uses 15-bits for its colour is only done to make each colour uniform as using all 16-bits means one colour can display more colours (and besides, the single bit won't make any major visual difference anyway), not to mention that the fixed colour (read: background colour) needs to be adjusted too (each primary colour in the fixed colour uses the same register: 5 bits are used for the colour value itself whereas bits 5 to 7 determine which colours to write to).
If you judge CPU's by the size of their address bus, then MS-DOS was a 20-bit operating system and your PC is running now a 48-bit operating system.
@@vytah My understanding, CPUs bit sizing is based on it's memory allocation. 32-bit means it can allocate up to 32-bit amount of memory. Same as 64-bit. 64-bit addressing of memory.
MS-DOS, Windows, Linux, etc are Operating System. Not CPUs.
@@baddmatt9588 Intel x64 supports up to 48 bits (currently) of virtual address bits and my particular CPU claims to have 39 physical lines. So is my CPU 39-bit, 48-bit?
Of course not. Though I'm not sure if the pointer size (64 bits) is what gave it its name of 64-bit.
The thing is, the bitness of each CPU is decided by convention and stuff such as address size, general purpose register size etc are mere heuristics.
By the heuristic of general purpose registers, the Intel CPU in my laptop, the ARM (Cortex A53) CPUs in my phone and my RPI are 64-bit and the Intel 8086 is a 16-bit (with 20-bit addresses). The 65816 in the SNES is 16-bit due to its 16-bit registers (though it is claimed to be 8/16 bit due to the selectability between 8-bit and 16-bit registers; that's just another oddity in the naming, but they wanted to market that selectability so this stuck), while the 6502 is a definitely 8-bit CPU even though the address space is 16-bit.
Look at the general purpose registers. Not address sizes, not other heuristics. The size of the general purpose registers determine the bitness of a CPU.
If you look at the largest register, my CPU would be 512-bit due to the AVX registers. Old 32-bit-only Intel CPUs would be 80-bit because their FPU (which is inside the CPU since the '486) works with 80-bit floating point values (which some C compilers expose as "long double"). Of course that isn't a good heuristic!
Wait, what!? 6502 emulation mode? I never heard about that before. You mean there's a way to execute 6502 assembly in the SNES CPU? What else is compatible with the NES? Not much I assume, otherwise we would have seen retrocompatibility back then. But I guess that explains some ports that are way too close to their NES counterparts, like Ninja Gaiden Trilogy. At least the logic could be ported, right?
Yes, it's a standard feature of the 65816. Almost all SNES games switch to native mode almost immediately on boot though.
The 65816 instruction set is a strict superset of the 6502's (as long as you don't rely on the "illegal" opcodes of the latter.) This similarity would generally have made it very easy to port NES code to the SNES. I imagine Super Mario All-Stars made good use of this. Has anyone actually checked? How much code in SMAS is copied verbatim from the original NES games?
@@0x5D That's amazing. Unlike Sega, Nintendo wasn't very famous for retrocompatibility at the time and I don't remember ever reading about this before, but yet... It was there all the time.
Now I'm also curious about SMAS.
This might have been mentioned already. At 1:10 you show the number 16777215. But say the number 16777216.
obligatory pedantic comment that kilobytes (kB, 1000 bytes) are not the same thing as kibibytes (kiB, 1024 bytes), and megabytes (MB, 1000000 bytes) are not the same as mebibytes (MiB, 1048576 bytes)
person one: "press 'F' to pay respects"
person two: "you know there are 16 people here right?"
person one: "oh, fork, now these 'F's are making hex 'FFFF FFFF FFFF FFFF' so now it's equal to -1"