Jekyll2023-12-03T06:52:13+00:00https://b13rg.github.io/feed.xmlBrendan’s WebsiteStuff about old code, vintage computers, and anything elseBrendan ByersIcebergByers@protonmail.comExploring the Gameboy Memory Bank Controller2020-12-01T00:00:00+00:002020-12-01T00:00:00+00:00https://b13rg.github.io/Gameboy-MBC-Analysis<p><img src="/images/MBC/header.JPG" alt="Array of Carts" /></p>
<p>Without a game cartridge, a Gameboy is just displays “Gameboy” and freezes.
Once slotted in, the bits and bytes contained within a cartridge created countless worlds and memories.
How did a Gameboy cartridges store such a wide variety of games, while also enabling things like save files, rumble, and even infrared communication?</p>
<p>In this article, we will examine the Memory Bank Controllers (MBC) contained inside the cartridge, and how they enabled the worlds of Pokemon, Zelda, and countless other to become a reality in the hands of children and adults everywhere.
To start, we will define what exactly a Memory Bank Controller is, and the different types that were available.
We’ll also analyze some usage statistics about how common they were in cartridges, and what types were used the most.</p>
<p>Next we’ll look at how the Gameboy determined the cartridge type by examining the game ROM header.
Finally, we’ll take a look at some real examples from my own game collection and see how the MBC was applied in practice.</p>
<hr />
<p>Table of Contents</p>
<ul>
<li><a href="#the-mbc">The MBC</a></li>
<li><a href="#usage-statistics">Usage Statistics</a></li>
<li><a href="#the-cartridge-header">The Cartridge Header</a></li>
<li><a href="#cartridge-hardware">Cartridge Hardware</a></li>
<li><a href="#no-mbc">No MBC</a>
<ul>
<li><a href="#alleyway">Alleyway</a></li>
<li><a href="#dr-mario">Dr. Mario</a></li>
<li><a href="#tetris">Tetris</a>
<ul>
<li><a href="#cart-1">Cart 1</a></li>
<li><a href="#cart-2">Cart 2</a></li>
</ul>
</li>
<li><a href="#yakuman">Yakuman</a></li>
</ul>
</li>
<li><a href="#mbc1">MBC1</a>
<ul>
<li><a href="#baseball">Baseball</a></li>
<li><a href="#frogger">Frogger</a></li>
<li><a href="#super-mario-land">Super Mario Land</a></li>
</ul>
</li>
<li><a href="#mbc3">MBC3</a>
<ul>
<li><a href="#pokemon-gold-version">Pokemon Gold Version</a></li>
<li><a href="#pokemon-silver-version-usa">Pokemon Silver Version USA</a></li>
<li><a href="#pokemon-silver-version-jp">Pokemon Silver Version JP</a></li>
</ul>
</li>
<li><a href="#mbc5">MBC5</a>
<ul>
<li><a href="#monster-rancher-battle-card-gb">Monster Rancher Battle Card GB</a></li>
<li><a href="#pokemon-pinball">Pokemon Pinball</a></li>
</ul>
</li>
<li><a href="#further-reading">Further Reading</a></li>
</ul>
<hr />
<h2 id="the-mbc">The MBC</h2>
<p>Memory Bank Controller were a part of many cartridge games developed for the Gameboy and Gameboy color.
It allowed the cartridge to not only address larger amounts of RAM and ROM, but to also have additional hardware that the Gameboy could utilize.
The MBCs were most commonly paired with larger ROM and additional RAM, but different MBCs also allowed the use of real time clocks, rumble, and even a light sensor.</p>
<p>A normal cartridge had 16 address lines, allowing the Gameboy to address a maximum of 64KB of ROM on the cartridge without an MBC.
In practice the maximum ROM size of a game without an MBC was 32KB.
Games like <a href="#tetris">Tetris</a> and <a href="#dr-mario">Dr. Mario</a> were 32KB or less in size, so didn’t require a MBC to operate.
This allowed for very simple PCB layouts, as the single ROM chip would be directly connected to the cartridge pins.
By placing an MBC between the console and the cartridge ROM/RAM, it could translate special reads and writes to facilitate the bank switching.</p>
<p>ROM data on a cartridge would be split into 16KB “banks” that could be swapped out at will by the game.
The first bank, <code class="language-plaintext highlighter-rouge">00</code>, would be always mounted at <code class="language-plaintext highlighter-rouge">0x0000-0x3FFF</code> in the Gameboy’s memory map.
This first bank usually contained code that was used commonly, as it would always be present and accessible by the program.
The game would be able to swap out any additional banks by writing values to special areas of the memory map, which would instruct the MBC what bank to switch to.
The selected bank would be mounted from <code class="language-plaintext highlighter-rouge">0x4000-0x7FFF</code>, right next to the area of memory that was bank <code class="language-plaintext highlighter-rouge">00</code>.</p>
<p>RAM banks behaved similarly, though it only mounted 8KB at a time.
That data was mounted at addresses <code class="language-plaintext highlighter-rouge">0xA000-0xBFFF</code> and was able to be both read and written to (as one would expect).
Many games took advantage of having extra RAM on the cartridge because the Gameboy DMG only had 8KB available internally.
The Gameboy color bumped that to 32KB, but that could still be constraining for larger titles.
For a deeper dive into the specifics of how games performed ROM and RAM bank switching, check out my article here: <a href="Gameboy-Bank-Switching/">Gameboy DMG ROM and RAM Bank Switching</a>.</p>
<p>When developing a game, it was and still is important to consider the size of the final product (unless you’re Call of Duty).
The size of the game and add-ons like RAM controlled what type of memory bank controller would be required.
The following types of memory bank controllers were usually available for use:</p>
<table>
<tbody>
<tr>
<td>Type</td>
<td>Max ROM</td>
<td>Max RAM</td>
<td>Info</td>
</tr>
<tr>
<td>None</td>
<td>32KB</td>
<td>8KB</td>
<td>No bank controller, just a ROM chip and potentially 1 bank’s worth of RAM</td>
</tr>
<tr>
<td>MBC1</td>
<td>2MB</td>
<td>32KB</td>
<td>The basic Gameboy MBC</td>
</tr>
<tr>
<td>MBC2</td>
<td>256KB</td>
<td>512x4 bits</td>
<td>Data in RAM consists of 4 bit values</td>
</tr>
<tr>
<td>MBC3</td>
<td>2MB</td>
<td>64KB</td>
<td>Similar to MBC1, also included addition of a real time clock</td>
</tr>
<tr>
<td>MBC5</td>
<td>8MB</td>
<td>1MB</td>
<td>Supported the light sensor, and a rumble motor</td>
</tr>
<tr>
<td>MBC6</td>
<td>1MB</td>
<td>32KB</td>
<td>Only used for one game: Net de Get: Minigame @ 100. Had separate, switchable ROM and RAM sets plus flash memory. ROM banks were 8KB and RAM banks were 4KB</td>
</tr>
<tr>
<td>MBC7</td>
<td>8MB</td>
<td>1MB</td>
<td>Contained additional 256 byte EEPROM and 2-axis accelerometer. Similar to MBC5</td>
</tr>
<tr>
<td>MMM01</td>
<td>2MB</td>
<td>32KB</td>
<td>A “metamapper” for a game collection, which switches between sets of banks</td>
</tr>
<tr>
<td>Tama5</td>
<td>?</td>
<td>?</td>
<td>Custom MBC designed by Bandai for a single game, Tamagotchi 3</td>
</tr>
<tr>
<td>HuC-1</td>
<td>2MB</td>
<td>32KB</td>
<td>Customer MBC designed by Hudson, supports infrared LED input.</td>
</tr>
<tr>
<td>HuC-3</td>
<td>2MB</td>
<td>32KB</td>
<td>Customer MBC designed by Hudson that adds a RTC and piezo buzzer to the HuC-1</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td><a href="https://mgba-emu.github.io/gbdoc">Source 1</a> <a href="https://gbdev.io/pandocs/#memory-bank-controllers">Source 2</a></td>
</tr>
</tbody>
</table>
<p>A note about the MMM01, it is a “metamapper” that is used in the game collection (Momotarō Collection 2 and Taito Variety Pack).
It provides a boot menu that allows the user to select a game before locking itself down into a separate “normal” mapper mode that only exposes certain banks to the game inside the collection.
To read more about the specifics, including an interesting VHDL design, check out this <a href="https://wiki.tauwasser.eu/view/MMM01">wiki page</a>.</p>
<p>Gameboy cartridges most commonly used no MBC at all, or MBC type 1,2, and 5.
MBC 3, 6 and 7 were usually reserved for special circumstances and didn’t see as much use.
The different types enabled developers to use hardware like real time clocks, RAM, batteries for saving, rumble, and even a light sensor.
Multiple memory controllers were made to help control the cost of producing the cartridge.
While it would be convenient to have a “One size fits all” controller that could dynamically accommodate add-ons and varying amounts of ROM and RAM, it would have been an expensive chip to produce.
By producing a variety of types, game developers could select the MBC that would best accommodate their game.</p>
<h2 id="usage-statistics">Usage Statistics</h2>
<p>The <a href="https://gbhwdb.gekkio.fi">Game Boy hardware database</a> is a community-created database of gameboy cartridges.
It contains detailed information and photos of various cartridges and their internal components.
There are 316 distinct Gameboy game entries, out of 1,049 DMG + 576 GBC games (1,625 total).
There are many games missing, but I figure it should be a good enough sample that we should at least be able to discern some trends from the data.</p>
<p>I grabbed a data dump, loaded it into sqlite3 and ran some queries over it to get some more information about what types of bank controllers were used over time.
You can view the same dataset I used <a href="/files/MBC/cartridges.csv">here</a>, or grab the most up-to-date copy from <a href="https://gbhwdb.gekkio.fi/static/export/cartridges.csv">here</a>.
The query I used counted how many distinct game titles used each MBC type by year.
It gives a rough view of both the number of games released and the controller types used in those games each year.</p>
<p><img src="/images/MBC/MBC_Types_Year.png" alt="Chart of " />
<a href="/images/MBC/MBC_Types_Year.png">Full size</a></p>
<table>
<tbody>
<tr>
<td>Year</td>
<td>None</td>
<td>MBC1A</td>
<td>MBC1B</td>
<td>MBC1B1</td>
<td>MBC2A</td>
<td>MBC3</td>
<td>MBC30</td>
<td>MBC3A</td>
<td>MBC3B</td>
<td>MBC5</td>
<td>MBC6</td>
<td>MBC7</td>
<td>TAMA5</td>
<td>MMM01</td>
<td>HuC-1</td>
<td>HuC-1A</td>
<td>HuC-3</td>
<td>Year</td>
</tr>
<tr>
<td>1989</td>
<td>4</td>
<td>2</td>
<td>1</td>
<td> </td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1989</td>
</tr>
<tr>
<td>1990</td>
<td>9</td>
<td>2</td>
<td>12</td>
<td> </td>
<td>2</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1990</td>
</tr>
<tr>
<td>1991</td>
<td>3</td>
<td> </td>
<td>21</td>
<td> </td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1991</td>
</tr>
<tr>
<td>1992</td>
<td> </td>
<td> </td>
<td>11</td>
<td>2</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1992</td>
</tr>
<tr>
<td>1993</td>
<td> </td>
<td> </td>
<td>4</td>
<td>7</td>
<td>2</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1993</td>
</tr>
<tr>
<td>1994</td>
<td> </td>
<td> </td>
<td>5</td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1994</td>
</tr>
<tr>
<td>1995</td>
<td> </td>
<td> </td>
<td>7</td>
<td>8</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1995</td>
</tr>
<tr>
<td>1996</td>
<td>1</td>
<td> </td>
<td>9</td>
<td>6</td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td>1996</td>
</tr>
<tr>
<td>1997</td>
<td>2</td>
<td> </td>
<td>7</td>
<td>20</td>
<td>3</td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1</td>
<td> </td>
<td>1</td>
<td> </td>
<td> </td>
<td>1997</td>
</tr>
<tr>
<td>1998</td>
<td> </td>
<td> </td>
<td>15</td>
<td>12</td>
<td>1</td>
<td>6</td>
<td> </td>
<td>7</td>
<td> </td>
<td>6</td>
<td> </td>
<td> </td>
<td>1</td>
<td> </td>
<td>1</td>
<td>1</td>
<td>3</td>
<td>1998</td>
</tr>
<tr>
<td>1999</td>
<td> </td>
<td> </td>
<td>2</td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td>3</td>
<td> </td>
<td>21</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1</td>
<td> </td>
<td>1</td>
<td>1999</td>
</tr>
<tr>
<td>2000</td>
<td>2</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1</td>
<td>4</td>
<td>3</td>
<td>32</td>
<td> </td>
<td>2</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>2000</td>
</tr>
<tr>
<td>2001</td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>9</td>
<td>13</td>
<td>1</td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>2001</td>
</tr>
<tr>
<td>2002</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>2</td>
<td>4</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>2002</td>
</tr>
<tr>
<td>2003</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>1</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>2003</td>
</tr>
</tbody>
</table>
<p>Query: <code class="language-plaintext highlighter-rouge">SELECT COUNT(DISTINCT "name"), COALESCE(NULLIF("mapper_kind",''), 'None'), "board_year" FROM cart WHERE DISTINCT "name" GROUP BY "mapper_kind", "board_year" ORDER BY "board_year", "mapper_kind";</code></p>
<p>For the first 7 years, we really only see the MBC1 and MBC2 used.
The MBC2 was used sparingly.
In terms of ROM space, it had 1/8th the space of the MBC1 but 8x the space of just a ROM with no MBC.
It also had 128 Bytes of RAM that was split into 4-byte chunks.
It seems that it was the simplest MBC available to game developers, meant for games that required more storage than just a ROM chip, but didn’t need all the capabilities of MBC1.</p>
<p>Between the different revisions of the MBC1, the MBC1B was used the most.
There are a few MBC1A entries, but they were only present in Japanese titles during the first two years of the gameboy.
The MBC1B probably fixed bugs present in the MBC1A, but I haven’t been able to find any concrete evidence describing what those issues might be, I’m just going of the naming scheme.
I think the difference between the MBC1B and MBC1B1 was less severe, possibly something to do with power consumption or speed since it is only a “minor version” improvement.
The MBC1B1 seemed to be used interchangeably with the normal MBC1B, as shown by the mapper type entries for <code class="language-plaintext highlighter-rouge">Donkey Kong Land III (USA, Europe) (Rev 1) (SGB Enhanced)</code>, where we can see it using both types over a period of two years:</p>
<table>
<thead>
<tr>
<th>MBC</th>
<th>PCB Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>MBC1B</td>
<td>Jul/1998</td>
</tr>
<tr>
<td>MBC1B1</td>
<td>Jul/1998</td>
</tr>
<tr>
<td>MBC1B1</td>
<td>Aug/1998</td>
</tr>
<tr>
<td>MBC1B</td>
<td>Jun/1999</td>
</tr>
</tbody>
</table>
<p>The MBC3 only started to be used in 1998, the same year the Gameboy Color was released.
Before that point, we really only see games use an MBC1, MBC2, or no MBC at all.
Once the MBC3 was released, it was used primarily for newer Gameboy Color games, but it also saw some use in games targeted for the Gameboy DMG, like <a href="https://www.youtube.com/watch?v=jbbMLLPZNnU">Mary Kate and Ashley’s Pocket Planner</a>.</p>
<p>Similar to the MBC1, we can also see hardware lifecycle events for the MBC3 over the years it was used.
It seems that the change from MBC3 -> MBC3A -> MBC3B was much more absolute than MBC1A -> MBC1B -> MBC1B1.
After 1998, Nintendo seemed to transition fully to the MBC3A, as we don’t see any MBC3 entries; after 2000 we see the same trend with the MBC3A and MBC3B.
The fact that we don’t see any use of a previous version in the year following the introduction of newer version leads me reason that the new versions fixed bugs in the hardware, instead of performance improvements like the MBC1B -> MBC1B1 update.</p>
<p>When a new console is released, it usually takes a little while for game developers to start using it to it’s fullest potential.
We are able to see that practice here with the MBC1 and MBC5 in the two years following each of their releases.</p>
<p>In 1990, you can see an increase of use across the available MBC types: “None”, MBC1, and MBC2.
Part of the growth in the year following the Gameboy DMG release can be contributed to the release dates of the Gameboy in April (JP), late July (USA), and late September (EU).
I assume that by waiting until the year following the release, developers have a bit more time with the hardware and can apply more polish to their games.
In 1991, we see a sharp drop off in games with just a ROM, and a large increase of MBC1 type games.
From 1992 to 1995, all the games end up using an MBC. with MBC1B and MBC1B1 seeing the bulk of the action.</p>
<p>There is a similar trend with the adoption of the MBC5 between 1998 and 2000.
Between 1998 and 1999, there was a large drop in MBC1 use, and a humongous increase in MBC5.
The MBC5 was a big improvement over the MBC1, and also had support for additional hardware additions to the cartridge.
1998 had about 50% of the games use a MBC1 style controller, with varied use across the other types.
In 1999 however, there is a huge drop in MBC1 use and a large jump in MBC5 use.
The MBC5 became available with the release of the Gameboy color (1998), and the sharp increase in use in 1999 and 2000 show how valuable the extra capabilities of the controller were.
After 1999, we don’t see any more of the MBC1 and just a smattering of use of ROMs without an MBC.</p>
<p>In 2001, the Gameboy Advance was released, and with it a completely new cartridge called the GamePak.
The new cartridge was incompatible with the old type, primarily because the Gameboy Advance used an ARM processor instead of a Z-80 clone like the Gameboy DMG and CGB.
This is the same reason the Nintendo DS is only able to play Advance games, nothing prior.
The new cartridge had 24 address lines instead of 16, and the entire cartridge ROM was in the memory map presented to the game, removing the need for bank switching.
You can read more about the GamePak cartridge <a href="https://reinerziegler.de.mirrors.gg8.se/GBA/gba.htm">here</a>.</p>
<p>With the release of the Gameboy Advance, we see a sharp decline in the number of titles released.
Games were still released for the Gameboy Color up until 2003.
Surprisingly, the last Gameboy DMG games were released in Japan in 2001, over a decade since the handheld was first released.</p>
<hr />
<h2 id="the-cartridge-header">The Cartridge Header</h2>
<p>When a cartridge is inserted into a Gameboy, it needs some way to communicate it’s hardware properties to the boot loader.
This is done through the cartridge header.
When preparing a game to be placed on a cartridge, a header is placed at the start of the ROM.
This header is present on all cartridges at addresses <code class="language-plaintext highlighter-rouge">0x100-0x14F</code>.
It’s the first thing that is read by the Gameboy and contains bits of information describing different properties of software and hardware.</p>
<p>The cartridge header stores information like the first 16 characters of the game’s title (<code class="language-plaintext highlighter-rouge">0x134-0x143</code>), region (<code class="language-plaintext highlighter-rouge">0x14a</code>), and even the nintendo logo (<code class="language-plaintext highlighter-rouge">0x104-0x133</code>).
This is the same logo that is stored in the Gameboy’s boot loader, and is used to check if the cartridge is legitimate.
If it is not correct, the game won’t load.
It also allowed Nintendo to have a stronger case against 3rd party companies making their own cartridges, as the nintendo logo is copyrighted.</p>
<p>The cartridge type is stored as a hex code at address <code class="language-plaintext highlighter-rouge">0x147</code>.
The hex code described the hardware configuration of the game cartridge.
Not only did it accommodate all the MBC plus hardware configurations, it also had codes for special cartridges like the pocket camera and 3rd party MBCs.</p>
<table>
<tbody>
<tr>
<td>Code</td>
<td>Type</td>
<td>Code</td>
<td>Type</td>
</tr>
<tr>
<td>00h</td>
<td>ROM Only</td>
<td>19h</td>
<td>MBC5</td>
</tr>
<tr>
<td>01h</td>
<td>MBC1</td>
<td>1Ah</td>
<td>MBC5+RAM</td>
</tr>
<tr>
<td>02h</td>
<td>MBC1+RAM</td>
<td>1Bh</td>
<td>MBC5+RAM+Battery</td>
</tr>
<tr>
<td>03h</td>
<td>MBC1+RAM+Battery</td>
<td>1Ch</td>
<td>MBC5+Rumble</td>
</tr>
<tr>
<td>05h</td>
<td>MBC2</td>
<td>1Dh</td>
<td>MBC5+Rumble+RAM</td>
</tr>
<tr>
<td>06h</td>
<td>MBC2+Battery</td>
<td>1Eh</td>
<td>MBC5+Rumble+RAM+Battery</td>
</tr>
<tr>
<td>08h</td>
<td>ROM+RAM</td>
<td>20h</td>
<td>MBC6</td>
</tr>
<tr>
<td>09h</td>
<td>ROM+RAM+Battery</td>
<td>22h</td>
<td>MBC7+Sensor+Rumble+RAM+Battery</td>
</tr>
<tr>
<td>0Bh</td>
<td>MMM01</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>0Ch</td>
<td>MMM01+RAM</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>0Dh</td>
<td>MMM01+RAM+Battery</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>0Fh</td>
<td>MBC3+Timer+Battery</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>10h</td>
<td>MBC3+Timer+RAM+Battery</td>
<td>FCh</td>
<td>Pocket Camera</td>
</tr>
<tr>
<td>11h</td>
<td>MBC3</td>
<td>FDh</td>
<td>BANDAI TAMA5</td>
</tr>
<tr>
<td>12h</td>
<td>MBC3+RAM</td>
<td>FEh</td>
<td>HuC3</td>
</tr>
<tr>
<td>13h</td>
<td>MBC3+RAM+Battery</td>
<td>FFh</td>
<td>HuC1+RAM+Battery</td>
</tr>
<tr>
<td> </td>
<td><a href="https://gbdev.io/pandocs/#_0147-cartridge-type">Source</a></td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<p>Given a cartridge ROM and this chart, it is very easy to find the cartridge type of a game by grabbing bytes at the right addresses.
If you have ROMs of games, you can peek these values using <code class="language-plaintext highlighter-rouge">xxd</code> in the terminal.
Here are some examples of the cart title and type from a few different games:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ xxd -seek 0x134 -len 16 pokecrystal.gbc
00000134: 504d 5f43 5259 5354 414c 0042 5954 45c0 PM_CRYSTAL.BYTE.
$ xxd -plain -seek 0x147 -len 1 pokecrystal.gbc
10
$ # MBC3+TIMER+RAM+BATTERY
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ xxd -seek 0x134 -len 16 'Pokemon Trading Card Game (U) [C][!].gbc'
00000134: 504f 4b45 4341 5244 0000 0041 5851 4580 POKECARD...AXQE.
$ xxd -plain -seek 0x147 -len 1 'Pokemon Trading Card Game (U) [C][!].gbc'
1b
$ # MBC5 + RAM + Battery
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ xxd -seek 0x134 -len 16 'SpongeBob SquarePants - Legend of the Lost Spatula (USA).gbc'
00000134: 5342 5350 204c 4f54 4c53 2142 5150 45c0 SBSP LOTLS!BQPE.
$ xxd -plain -seek 0x147 -len 1 'SpongeBob SquarePants - Legend of the Lost Spatula (USA).gbc'
19
$ # MBC5
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ xxd -seek 0x134 -len 16 'Game de Hakken!! Tamagotchi - Osutchi to Mesutchi (Japan) (SGB Enhanced).gb'
00000134: 4742 2054 414d 4147 4f54 4348 4920 3300 GB TAMAGOTCHI 3.
$ xxd -plain -seek 0x147 -len 1 'Game de Hakken!! Tamagotchi - Osutchi to Mesutchi (Japan) (SGB Enhanced).gb'
fd
$ # Bandai Tama5 (Built in alarm for when to feed your Tamagotchi!)
</code></pre></div></div>
<hr />
<h2 id="cartridge-hardware">Cartridge Hardware</h2>
<p>In this next section, I took pictures of most of my Gameboy games and recorded the different chips on the cart.
They’ve been split into sections based on the MBC type the cartridge uses.
For each game, there is a picture of the cartridge and the PCB.
For webpage size reasons, there is a link below each image to the full size original.
There is also a table below each game that notates the board and chip labels.</p>
<p>The cases contain two bits of interesting info: the game ID and a case stamp.
The game ID is in the format <code class="language-plaintext highlighter-rouge">[Handheld type]{3}-[Game identifier]{3,4}-[Region]{2,3}-[Revision]{0,1}</code>.
For the games below, the handheld type is usually <code class="language-plaintext highlighter-rouge">DMG</code> for the original Gameboy and <code class="language-plaintext highlighter-rouge">CGB</code> for the Gameboy Color.
The game identifier is usually 3 or 4 characters long, and is similar to the ID on the ROM chip.
It uniquely identifies what game it is.
The region is 2 or 3 characters and describes the intended region of the game.
The most common that I’ve seen is <code class="language-plaintext highlighter-rouge">USA</code> and <code class="language-plaintext highlighter-rouge">JP</code>, but <code class="language-plaintext highlighter-rouge">EUR</code> for Europe and <code class="language-plaintext highlighter-rouge">AUS</code> for Australia also exist.
Some carts also include a optional number at the end, most likely corresponding to the revision number of the game.</p>
<p>The case stamp is a label imprinted on the label of the case consisting of two digits and a letter.
It can be hard to see in some cases, but I’ve done my best to record it here.
I’m not sure what it means, but I suspect it may have something to do with the cartridge manufacturing.
They follow the format <code class="language-plaintext highlighter-rouge">[0-3]{1}[0-4]{1}[A-D]{0,1}</code></p>
<p>Inside the cart, the PCB also has special marking on both the PCB itself and the ROM chip that contains the game code.
PCB board is in the format <code class="language-plaintext highlighter-rouge">[Handheld type]{3}-[PCB type]{4}-[Revision]{2}</code>.
The handheld type on the case, cartridge and ROM chip should all match.
The PCB type depends on the hardware configuration required by the game.
Games that had the same MBC and extra hardware usually had the same type, but not always.
Finally, the revision declared what revision the board was.
For example, <a href="#frogger">Frogger</a> (revision <code class="language-plaintext highlighter-rouge">10</code>) and <a href="#super-mario-land">Super Mario Land</a> (revision <code class="language-plaintext highlighter-rouge">01</code>) and see that despite having the same MBC and hardware, the boards are slightly different.
Only revisions I’ve seen here and in the Gameboy hardware database are <code class="language-plaintext highlighter-rouge">01</code> and <code class="language-plaintext highlighter-rouge">10</code>, binary 1 and 2.</p>
<p>The ROM chips follow a similar format to the game cartridge, only leaving off the region code.
ROM chips use the format <code class="language-plaintext highlighter-rouge">[Handheld type]{3}-[Game identifier]{3,4}-[Revision]{1}</code>.</p>
<p>Now on to the pictures!</p>
<h2 id="no-mbc">No MBC</h2>
<h3 id="alleyway">Alleyway</h3>
<p><img src="/images/MBC/alleyway_case.JPG" alt="DMG-AW-USA" width="500px" />
<a href="/images/MBC/originals/alleyway_case.JPG">Original</a></p>
<p>Release: DMG-AW-USA</p>
<p>Case Stamp: 05</p>
<p><img src="/images/MBC/alleyway_pcb.JPG" alt="DMG-AAA-03" width="500px" />
<a href="/images/MBC/originals/alleyway_pcb.JPG">Original</a></p>
<p>Board Type: DMG-AAA-03</p>
<p>ROM Type: DMG-AWA-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 34 1990</td>
<td>DMG-AWA-0</td>
</tr>
</tbody>
</table>
<h3 id="dr-mario">Dr. Mario</h3>
<p><img src="/images/MBC/dr_mario_case.JPG" alt="DMG-VU-USA" width="500px" />
<a href="/images/MBC/originals/dr_mario_case.JPG">Original</a></p>
<p>Release: DMG-VU-USA</p>
<p>Case Stamp: 22</p>
<p><img src="/images/MBC/dr_mario_pcb.JPG" alt="DMG-AAA-03" width="500px" />
<a href="/images/MBC/originals/dr_mario_pcb.JPG">Original</a></p>
<p>Board Type: DMG-AAA-03</p>
<p>ROM Type: DMG-VUA-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 34 1990</td>
<td>DMG-VUA-0</td>
</tr>
</tbody>
</table>
<h3 id="tetris">Tetris</h3>
<h4 id="cart-1">Cart 1</h4>
<p><img src="/images/MBC/tetris_case_1.JPG" alt="DMG-TR-USA" width="500px" />
<a href="/images/MBC/originals/tetris_case_1.JPG">Original</a></p>
<p>Release: DMG-TR-USA</p>
<p>Case Stamp: 23 A</p>
<p><img src="/images/MBC/tetris_pcb_1.JPG" alt="DMG-AAA-03" width="500px" />
<a href="/images/MBC/originals/tetris_pcb_1.JPG">Original</a></p>
<p>Board Type: DMG-AAA-03</p>
<p>ROM Type: DMG-TRA-1</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 14 1990</td>
<td>DMG-TRA-1</td>
</tr>
</tbody>
</table>
<h4 id="cart-2">Cart 2</h4>
<p><img src="/images/MBC/tetris_case_2.JPG" alt="DMG-TR-USA" width="500px" />
<a href="/images/MBC/originals/tetris_case_2.JPG">Original</a></p>
<p>Release: DMG-TR-USA</p>
<p>Case Stamp: 23 A</p>
<p><img src="/images/MBC/tetris_pcb_2.JPG" alt="DMG-AAA-03" width="500px" />
<a href="/images/MBC/originals/tetris_pcb_2.JPG">Original</a></p>
<p>Board Type: DMG-AAA-03</p>
<p>ROM Type: DMG-TRA-1</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 9 1991</td>
<td>DMG-TRA-1</td>
</tr>
</tbody>
</table>
<h3 id="yakuman">Yakuman</h3>
<p><img src="/images/MBC/yakuman_case.JPG" alt="DMG-MJJ" width="500px" />
<a href="/images/MBC/originals/yakuman_case.JPG">Original</a></p>
<p>Release: DMG-MJJ</p>
<p>Case Stamp: 22 A</p>
<p><img src="/images/MBC/yakuman_pcb.JPG" alt="DMG-AAA-03" width="500px" />
<a href="/images/MBC/originals/yakuman_pcb.JPG">Original</a></p>
<p>Board Type: DMG-AAA-03</p>
<p>ROM Type: DMG-MJJ-1</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 14 1990</td>
<td>DMG-MJJ-1</td>
</tr>
</tbody>
</table>
<h2 id="mbc1">MBC1</h2>
<h3 id="baseball">Baseball</h3>
<p><img src="/images/MBC/baseball_case.JPG" alt="DMG-BS-USA" width="500px" />
<a href="/images/MBC/originals/baseball_case.JPG">Original</a></p>
<p>Release: DMG-BS-USA</p>
<p>Case Stamp: 22</p>
<p><img src="/images/MBC/baseball_pcb.JPG" alt="DMG-BBA-02" width="500px" />
<a href="/images/MBC/originals/baseball_pcb.JPG">Original</a></p>
<p>Board Type: DMG-BBA-02</p>
<p>ROM Type: DMG-BSA-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 51 1989</td>
<td>DMG-BSA-0</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC1/1A/1B</td>
<td>Nintendo</td>
<td>Week 41 1989</td>
<td>MBC1A</td>
</tr>
</tbody>
</table>
<h3 id="frogger">Frogger</h3>
<p><img src="/images/MBC/frogger_case.JPG" alt="DMG-AFGE-USA" width="500px" />
<a href="/images/MBC/originals/frogger_case.JPG">Original</a></p>
<p>Release: DMG-AFGE-USA</p>
<p>Case Stamp: 12</p>
<p><img src="/images/MBC/frogger_pcb.JPG" alt="DMG-BEAN-10" width="500px" />
<a href="/images/MBC/originals/frogger_pcb.JPG">Original</a></p>
<p>Board Type: DMG-BEAN-10</p>
<p>ROM Type: DMG-AFGE-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Sharp</td>
<td>Week 4 1999</td>
<td>DMG-AFGE-0</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC1/1B/1B1</td>
<td>Nintendo</td>
<td>Week 51 1998</td>
<td>DMG MBC1B1</td>
</tr>
</tbody>
</table>
<h3 id="super-mario-land">Super Mario Land</h3>
<p><img src="/images/MBC/super_mario_land_case.JPG" alt="DMG-ML-USA" width="500px" />
<a href="/images/MBC/originals/super_mario_land_case.JPG">Original</a></p>
<p>Release: DMG-ML-USA</p>
<p>Case Stamp: 23 A</p>
<p><img src="/images/MBC/super_mario_land_pcb.JPG" alt="DMG-BEAN-01" width="500px" />
<a href="/images/MBC/originals/super_mario_land_pcb.JPG">Original</a></p>
<p>Board Type: DMG-BEAN-01</p>
<p>ROM Type: DMG-MLA-1</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>Nintendo</td>
<td>Week 37 1990</td>
<td>DMG-MLA-1</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC1/1A/1B</td>
<td>Nintendo</td>
<td>—</td>
<td>DMG-MBC1B</td>
</tr>
</tbody>
</table>
<h2 id="mbc3">MBC3</h2>
<h3 id="pokemon-gold-version">Pokemon Gold Version</h3>
<p><img src="/images/MBC/pokemon_gold_case.JPG" alt="GMD-AAUE-USA" width="500px" />
<a href="/images/MBC/originals/pokemon_gold_case.JPG">Original</a></p>
<p>Release: GMD-AAUE-USA</p>
<p>Case Stamp: 20</p>
<p><img src="/images/MBC/pokemon_gold_pcb.JPG" alt="DMG-KGDU-10" width="500px" />
<a href="/images/MBC/originals/pokemon_gold_pcb.JPG">Original</a></p>
<p>Board Type: DMG-KGDU-10</p>
<p>ROM Type: DMG-AAUE-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>MX</td>
<td>Date</td>
<td>DMG-AAUE-0</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC3A</td>
<td>Nintendo</td>
<td>Date</td>
<td>MBC3 A</td>
</tr>
<tr>
<td>U3</td>
<td>RAM</td>
<td>RAM</td>
<td>Hyundai</td>
<td>Week 29 2000</td>
<td>GM76C256CLLFW70</td>
</tr>
<tr>
<td>U4</td>
<td>RAM Protector</td>
<td>MM1134</td>
<td>Mitsumi</td>
<td>Week 7 1973</td>
<td>6735</td>
</tr>
</tbody>
</table>
<h3 id="pokemon-silver-version-usa">Pokemon Silver Version USA</h3>
<p><img src="/images/MBC/pokemon_crystal_usa_case.JPG" alt="DMG-AAXE-USA" width="500px" />
<a href="/images/MBC/originals/pokemon_crystal_usa_case.JPG">Original</a></p>
<p>Release: DMG-AAXE-USA</p>
<p>Case Stamp: 13</p>
<p><img src="/images/MBC/pokemon_crystal_usa_pcb.JPG" alt="DMG-KGDU-10" width="500px" />
<a href="/images/MBC/originals/pokemon_crystal_usa_pcb.JPG">Original</a></p>
<p>Board Type: DMG-KGDU-10</p>
<p>ROM Type: DMG-AAXE-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>MX</td>
<td>—</td>
<td>DMG-AAXE-0</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC3A</td>
<td>Nintendo</td>
<td>—</td>
<td>MBC-3 B</td>
</tr>
<tr>
<td>U3</td>
<td>RAM</td>
<td>RAM</td>
<td>BSI</td>
<td>Week 42 2000</td>
<td>BS62LV256SC-70</td>
</tr>
<tr>
<td>U4</td>
<td>RAM Protector</td>
<td>MM1134</td>
<td>Mitsumi</td>
<td>—</td>
<td>6735</td>
</tr>
</tbody>
</table>
<h3 id="pokemon-silver-version-jp">Pokemon Silver Version JP</h3>
<p><img src="/images/MBC/pokemon_silver_jp_case.JPG" alt="DMG-AAXJ-JPN" width="500px" />
<a href="/images/MBC/originals/pokemon_silver_jp_case.JPG">Original</a></p>
<p>Release: DMG-AAXJ-JPN</p>
<p>Case Stamp: 12 A</p>
<p><img src="/images/MBC/pokemon_silver_jp_pcb.JPG" alt="DMG-KFDN-10" width="500px" />
<a href="/images/MBC/originals/pokemon_silver_jp_pcb.JPG">Original</a></p>
<p>Board Type: DMG-KFDN-10</p>
<p>ROM Type: DMG-AAXJ-1</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>PRG</td>
<td>MX</td>
<td>—</td>
<td>MX23C8003-20 DMG-AAXJ-1</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC3A</td>
<td>Nintendo</td>
<td>—</td>
<td>MBC-3 A</td>
</tr>
<tr>
<td>U3</td>
<td>RAM</td>
<td>RAM</td>
<td>Sharp</td>
<td>Week 5 2000</td>
<td>LH52256CN-10LL</td>
</tr>
<tr>
<td>U4</td>
<td>RAM Protector</td>
<td>MM1134</td>
<td>Mitsumi</td>
<td>Week 40 1990</td>
<td>6735</td>
</tr>
</tbody>
</table>
<h2 id="mbc5">MBC5</h2>
<h3 id="monster-rancher-battle-card-gb">Monster Rancher Battle Card GB</h3>
<p><img src="/images/MBC/monster_rancher_case.JPG" alt="DMG-A6TE-USA" width="500px" />
<a href="/images/MBC/originals/monster_rancher_case.JPG">Original</a></p>
<p>Release: DMG-A6TE-USA</p>
<p>Case Stamp: 00</p>
<p><img src="/images/MBC/monster_rancher_pcb.JPG" alt="DMG-A08-01" width="500px" />
<a href="/images/MBC/originals/monster_rancher_pcb.JPG">Original</a>
Board Type: DMG-A08-01</p>
<p>ROM Type: DMG-A6TE-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>16M/32M/64M-MROM</td>
<td>MX</td>
<td>—</td>
<td>MX23C1603-12A DMG-A6TE-0</td>
</tr>
<tr>
<td>U2</td>
<td>Mapper</td>
<td>MBC-5</td>
<td>Nintendo</td>
<td>—</td>
<td>MBC5</td>
</tr>
<tr>
<td>U3</td>
<td>RAM</td>
<td>64K-SRAM</td>
<td>Sharp</td>
<td>Week 21 2000</td>
<td>LH5164AN-10L</td>
</tr>
<tr>
<td>U4</td>
<td>RAM Protector</td>
<td>MM1134A</td>
<td>Atmel</td>
<td>—</td>
<td>028 134A</td>
</tr>
</tbody>
</table>
<h3 id="pokemon-pinball">Pokemon Pinball</h3>
<p><img src="/images/MBC/pokemon_pinball_case_front.JPG" alt="DMG-VPHE-USA Front" width="500px" />
<a href="/images/MBC/originals/pokemon_pinball_case_front.JPG">Original</a></p>
<p><img src="/images/MBC/pokemon_pinball_case_back.JPG" alt="DMG-VPHE-USA Back" width="500px" />
<a href="/images/MBC/originals/pokemon_pinball_case_back.JPG">Original</a></p>
<p>Release: DMG-VPHE-USA</p>
<p>Case Stamp: 22</p>
<p><img src="/images/MBC/pokemon_pinball_pcb.JPG" alt="DMG-A04-01" width="500px" />
<a href="/images/MBC/originals/pokemon_pinball_pcb.JPG">Original</a></p>
<p>Board Type: DMG-A04-01</p>
<p>ROM Type: DMG-VPHE-0</p>
<table>
<thead>
<tr>
<th> </th>
<th>Chip</th>
<th>Board Label</th>
<th>Mfr.</th>
<th>Date</th>
<th>Chip Label</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>ROM</td>
<td>4M/8M MROM</td>
<td>MX</td>
<td>—</td>
<td>DMG-VPHE-0</td>
</tr>
<tr>
<td>U2</td>
<td>MBC</td>
<td>MBC5</td>
<td>—</td>
<td>Week 33 1999</td>
<td>LZ9GB31</td>
</tr>
<tr>
<td>U3</td>
<td>RAM</td>
<td>64K SRAM</td>
<td>Sharp</td>
<td>Week 9 1999</td>
<td>LH5164AN-10L</td>
</tr>
<tr>
<td>U4</td>
<td>RAM Protector</td>
<td>MM1134A</td>
<td>Atmel</td>
<td>—</td>
<td>—</td>
</tr>
</tbody>
</table>
<h2 id="further-reading">Further Reading</h2>
<ul>
<li><a href="Gameboy-Bank-Switching/">My article on Gameboy Bank Switching</a></li>
<li>
<p><a href="Gameboy_DMG/">My article on the Gameboy DMG</a></p>
</li>
<li><a href="https://gbdev.gg8.se/forums/viewtopic.php?id=544">Info about MBC6</a></li>
<li><a href="https://gbdev.gg8.se/forums/viewtopic.php?id=448">Info about MBC7</a></li>
<li><a href="https://wiki.tauwasser.eu/view/MMM01">Info about MMM01</a></li>
<li><a href="https://gbdev.gg8.se/forums/viewtopic.php?id=744">Info about HuC-3</a></li>
<li><a href="https://www.nintendo.co.uk/Support/Game-Boy-Pocket-Color/Product-information/Technical-data/Technical-data-619585.html">Official Nintendo Gameboy family technical data</a></li>
<li><a href="https://mgba-emu.github.io/gbdoc/#memory-bank-controllers">Open Gameboy Documentation</a></li>
<li><a href="https://gbdev.io/pandocs/#the-cartridge-header">Pan Docs cart info</a></li>
<li><a href="https://github.com/AntonioND/giibiiadvance/tree/master/docs">GiiBii Advance emulator docs</a></li>
<li><a href="https://gbhwdb.gekkio.fi/">Gameboy Hardware Database</a></li>
<li><a href="https://www.copetti.org/projects/consoles/game-boy/">Gameboy Architecture</a></li>
</ul>Brendan ByersIcebergByers@protonmail.comWithout a game cartridge, a Gameboy is just displays "Gameboy" and freezes. Once slotted in, the bits and bytes contained within a cartridge created countless worlds and memories. How did a Gameboy cartridges store such a wide variety of games, while also enabling things like save files, rumble, and even infrared communication?A Look at the Gameboy DMG2020-06-17T00:00:00+00:002020-06-17T00:00:00+00:00https://b13rg.github.io/Gameboy_DMG<p><img src="/images/GBDMG/Gameboy_DMG.jpg" alt="The Gameboy DMG" target="_blank" />
<a href="/images/GBDMG/originals/Gameboy_DMG.jpg">The Gameboy DMG</a></p>
<p>The original Gameboy was an 8-bit handheld console created by Nintendo.
It was technically their second handheld console, the first being the Game & Watch series.
The same team that developed the Game & Watch games also worked on development of the Gameboy, which went on sale on April 21, 1989 in Japan and July 31 in North America.
It was originally sold for only $89.95, about $185.99 in 2020 dollars.
It was Nintendo’s primary handheld console until the release of the Gameboy Color in 1998.</p>
<p>Before the Color, the Gameboy Pocket and Gameboy Light were released but they weren’t hugely different than the DMG, more like minor revisions than a new handheld.
Despite the color being release, the Gameboy DMG (Dot Matrix Game) continued to be sold until 2003, after the release of the Gameboy Advance.</p>
<p>The DMG had a total of 6 launch titles, though some were only released in specific regions:</p>
<table>
<thead>
<tr>
<th>Title</th>
<th style="text-align: center">JP</th>
<th style="text-align: center">NA</th>
<th style="text-align: center">EU</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alleyway</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
</tr>
<tr>
<td>Baseball</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
</tr>
<tr>
<td>Super Mario Land</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
</tr>
<tr>
<td>Tennis</td>
<td style="text-align: center">❌</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">❌</td>
</tr>
<tr>
<td>Tetris</td>
<td style="text-align: center">❌</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">✅</td>
</tr>
<tr>
<td>Yakuman</td>
<td style="text-align: center">✅</td>
<td style="text-align: center">❌</td>
<td style="text-align: center">❌</td>
</tr>
</tbody>
</table>
<p>By the end of it’s life, around 1,056 different games made for the system.
The last game released in Japan was <code class="language-plaintext highlighter-rouge">Shikakei Atama o Kore Kusuru: Kanji no Tatsujin</code> on March 30, 2001.
The last game released for both North America and Europe was <code class="language-plaintext highlighter-rouge">Pokemon Yellow</code> on October 19, 1999 and June 16, 2000 respectively.</p>
<p>Now let’s talk about this one specifically.</p>
<h2 id="case">Case</h2>
<p><img src="/images/GBDMG/DMG_Front.jpg" alt="The faceplate of the case" />
<a href="/images/GBDMG/originals/DMG_Front.jpg">The faceplate of the case</a></p>
<p>Compared to the plastic on the inside, it’s a little yellowed but that’s to be expected with how old it is.
I hope to eventually get my hands on some retro-bright and restore it back to it’s original grey.
I am especially happy with this Gameboy because it still has both the battery cover and the communication port cover.</p>
<h3 id="front">Front</h3>
<p>The screen takes up the largest part of the front, consisting of the screen itself and a plastic cover on top.
Along the top of the plastic cover is the text <code class="language-plaintext highlighter-rouge">DOT MATRIX WITH STEREO SOUND</code>.
Just below the screen the Gameboy proclaims it’s name to the world, with the text <code class="language-plaintext highlighter-rouge">Nintendo GAME BOY TM</code>.
Just to the left of the screen is a small red LED that shows when power is on.
It is simply labelled as <code class="language-plaintext highlighter-rouge">BATTERY</code>.
It’s useful for figuring out if you need to fix the contrast of the screen, get new batteries or have a deeper issue as in my case…</p>
<p>Below that is the buttons and speaker grill.
On the left is the D-Pad molded from black, which has a more mushy feel than later Gameboy handhelds.
It has a divot in the center and two slightly raised sections in each direction, which you can see if you look closely.
There are also small arrows in each direction molded on the case.</p>
<p>On the right is the A and B buttons, with the labeling on the case instead of being molded into the buttons like in later Gameboys.
These buttons are also molded from hard plastic, though in a dark red or maroon like color.</p>
<p>The start and select buttons are both molded from a silicon-like material, and are even mushier than the D-Pad.
One thing to notice is that they are angled, not parallel with the bottom of the case.
To me, it makes it feel more slick and futuristic.
The labels for the buttons are printed on the case, in the same direction as the A and B buttons, thought at a smaller font size.</p>
<p>Finally, the speaker grill is in the bottom right, outputting mono sound.
It has 6 “slots” for sound to come out of, but only 5 of them have holes cut through the case.</p>
<h3 id="back">Back</h3>
<p><img src="/images/GBDMG/DMG_Back_Open.jpg" alt="Back of the case with the battery door removed" />
<a href="/images/GBDMG/originals/DMG_Back_Open.jpg">Back of the case with the battery door removed</a></p>
<p>Serial #: <code class="language-plaintext highlighter-rouge">G06184423</code></p>
<h4 id="back-text">Back text</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MODEL NO. DMG-01
©1989 Nintendo
RATING : DC 6V 0.7W
BATTERY : SUM-3(AAa,R6)X4
PAT. PEND. MADE IN JAPAN
Complies with the limits for a Class B computing
device pursuant to Subpart J of Part 15 of FCC Rules.
</code></pre></div></div>
<p>The back of the case is much simpler than the front, but you’ll definitely spend more time staring at the front than the back anyway so it doesn’t matter too much.
Cartridges are loaded from the top, with the label facing out.
When switched on, the cartridge is held in place by a small tab on the on/off switch.</p>
<p>Below that slot is the “battery bay”, which holds 4 AA batteries.
A cover goes over the batteries, holding them in place.
It is held by a little clip at the top and two legs at the bottom of the plastic.</p>
<p>To open up the case, there’s 4 screws on the outside and 2 inside the battery bay that need to be removed.</p>
<h3 id="edges">Edges</h3>
<p><img src="/images/GBDMG/DMG_Top.jpg" alt="Top of the case" />
<a href="/images/GBDMG/originals/DMG_Top.jpg">Top of the case</a></p>
<p>On the top of the case is the On/Off switch.
To turn the console on, you move it toward the middle.
When you turn it on, the button has a bit of plastic sticking out that holds the cartridge in the slot.
This stops you from removing a cartridge while it is on.
This “feature” was later removed from later Gameboys, I think when designing the original Gameboy they were worried that people would pull the cartridge out at the wrong time and corrupt the save data for whatever they were playing.</p>
<p><img src="/images/GBDMG/DMG_Side_Right.jpg" alt="Right side of the case" />
<a href="/images/GBDMG/originals/DMG_Side_Right.jpg">Right side of the case</a></p>
<p>Text: <code class="language-plaintext highlighter-rouge">VOL ◢</code>, <code class="language-plaintext highlighter-rouge">EXT. CONNECTOR</code></p>
<p>On the right side, there is the communication port and volume knob.
The communication port is a 6-pin plug that allows one to connect to other Gameboys over a serial interface.
It had a variety of different modes, including a “Normal” mode for 1 to 1 connections, a “Multi-Play” mode for 1 to 1-4 connections where each had the same game, and a “Multi-Boot” mode.
I most often used it for trading Pokemon, and not much else.</p>
<p><img src="/images/GBDMG/DMG_Side_Left.jpg" alt="Left side of the case" />
<a href="/images/GBDMG/originals/DMG_Side_Left.jpg">Left side of the case</a></p>
<p>Text: <code class="language-plaintext highlighter-rouge">CONTRAST</code>, <code class="language-plaintext highlighter-rouge">USE ONLY DMG-03.-05</code>, <code class="language-plaintext highlighter-rouge">⭪ DC 6V</code></p>
<p>The left side has the contrast knob and a jack to plug in external power.
The knob allows you to adjust the contrast of the screen, which is extremely useful as it can take some tuning to get the screen to look right.
It is about a third of the thickness of the volume knob.
You have to fight against the ambient light around you, and as you play more and the battery drains it’ll start getting fainter.
There are mods to install a fancy backlit screen, but that’s a mod for a different day.</p>
<p>The plug is intended to be used with the rechargeable battery pack, which would plug in via a cable.
It was able to power the Gameboy on its own, and somewhat fixed the battery issue.</p>
<p><img src="/images/GBDMG/DMG_Bottom.jpg" alt="Case Booty" />
<a href="/images/GBDMG/originals/DMG_Bottom.jpg">Case Booty</a></p>
<p>On the bottom of the case is the headphone jack.
This allows headphones to be plugged in, letting you enjoy that sweet 8-bit stereo sound.
I think it is ironic that the headphone jack was included on the original Gameboy, but not on the Gameboy Advance SP, which was made 14 years later.</p>
<hr />
<h2 id="the-insides">The Insides</h2>
<p><img src="/images/GBDMG/DMG_Opened.jpg" alt="Two halves of the Gameboy, connected by a ribbon" />
<a href="/images/GBDMG/originals/DMG_Opened.jpg">Two halves of the Gameboy, connected by a ribbon</a></p>
<p>To open the case, you must remove 6 screws: 4 on back and 2 underneath the batteries.
Once those are removed, the case opens up into two sections connected by a ribbon cable, pivoting at the top.
The front section contains the I/O inputs, speaker and screen hardware.
The back section contains the main logic board, along with a power converter board and headphone jack board connected by wires to the logic board.</p>
<h3 id="screen-and-io-pcb">Screen and I/O PCB</h3>
<p><img src="/images/GBDMG/Screen_PCB_Front.jpg" alt="The fronts of the screen PCB" />
<a href="/images/GBDMG/originals/Screen_PCB_Front.jpg">The fronts of the screen PCB</a></p>
<p>Board Label: <code class="language-plaintext highlighter-rouge">©1989 Nintendo</code>, <code class="language-plaintext highlighter-rouge">DMG LCD-05</code></p>
<p>Most of the heavily lifting is done on the logic board so the front PCB is pretty simple, with lots of blank PCB space.
It’s attached to the front case piece with 10 screws, much more than the other PCB.
They are spaced carefully around the buttons and screen to try and provide the most support.
This PCB needs to withstand the pressure of the player pressing buttons, so the screws makes sure nothing warps or breaks in ways it shouldn’t.</p>
<p>The screen is a Sharp LH5028 160px x 144px monochrome LCD screen, capable of displaying 4 shades (2 bits worth) of green.
The datasheet for the original screen can be found <a href="/files/GBDMG/Sharp_LH1511_Datasheet.pdf">here</a>.
It rests on the PCB held in place by 3 clips part of the plastic screen housing.
The screen contains two ICs that control drawing the X and Y axis.
You can see the X axis chip in the image above, labeled <code class="language-plaintext highlighter-rouge">004</code>.
The ribbon for the X axis chip is held to the PCB by two small screws and a bar that is soldered across to hold it in place.</p>
<p>The front of the screen is glass, but is protected from damage and fingerprints by a plastic cover that attaches to the front of the case.
When the plastic screen is inevitably scratched, it is easy to swap it out without having to worry about the damage being permanent.
Because of their age and it’s effect on glue, many Gameboys have lost this screen.
Luckily, it’s very easy to pick up a pack of 4 on eBay for cheap that look brand new.</p>
<p>The screen is pretty bulky and “meh” compared to modern screens.
It requires the user to tune the contrast via a dial on the side.
To make matters worse, as the batteries lose energy, the screen will also start to dim forcing one to adjust it every so often.
One common modification is to swap out the screen with a modern, backlit screen.
In addition to just looking better and being able to play in the sun, new screens can display 4 shades of grey instead of the original olive green.</p>
<p><img src="/images/GBDMG/Screen_Buttons.jpg" alt="I/O PCB, pads and buttons" />
<a href="/images/GBDMG/originals/Screen_Buttons.jpg">I/O PCB, pads and buttons</a></p>
<p>The directional and A+B buttons are made of hard plastic, while the select and start are just soft buttons made of silicon.
On the PCB, the D-Pad has two contact pads for each direction, while all other buttons have 4 to capture button presses reliably.
The buttons are restored to their original position using silicon pads that go between the plastic button and the PCB, similar to a rubber dome keyboard.
The D-Pad pivots directly on the PCB, which over time wears a spot which luckily doesn’t rest on any contacts or lines.</p>
<p><img src="/images/GBDMG/Screen_in_Case.jpg" alt="Back of the screen PCB while mounted in the case" />
<a href="/images/GBDMG/originals/Screen_in_Case.jpg">Back of the screen PCB while mounted in the case</a></p>
<p>The back of the PCB is stamped with the text <code class="language-plaintext highlighter-rouge">005.22</code>, which matches number stamped on the other PCB’s heat sink.
This means that we have a system with original matching boards that haven’t been swapped out, and are most likely the same that were installed in the case when it was originally manufactured.</p>
<p>This PCB is very well labeled, with each screw hole being clearly circled and each component labeled.
At the bottom right on the back there is a circled letter <code class="language-plaintext highlighter-rouge">Z</code>.
There is also an extra hole, which is very clearly marked to not have a screw inserted.
There are also 3 simple spring type connectors that ground it to the logic board labeled <code class="language-plaintext highlighter-rouge">E1</code>, <code class="language-plaintext highlighter-rouge">E2</code>, and <code class="language-plaintext highlighter-rouge">E3</code>.
When installed in the case, they make contact with 3 ground points on the logic board.
to ensure that the front board has access to a solid ground, instead of trying to only use the ribbon cable.
The board includes hole cutouts for the larger capacitors, and space for the speaker and audio jack to slot in between the pcb and the case.</p>
<p>One interesting thing about the board is the use of jumper wires, labeled using the format <code class="language-plaintext highlighter-rouge">J#</code>.
Instead of using loose wires, there are specific cutouts in the ground layer of the PCB for the jumper to rest as to not cause shorts etc.
They act as a third PCB layer; this board only has traces on the front and back, with nothing sandwiched in the middle.</p>
<p>The speaker is a simple 8Ω one, labeled <code class="language-plaintext highlighter-rouge">2P22a 8Ω JPN 04359</code>.
It connects to the board via two wires that wrap their way around the speaker to the board.
It is directly connected to the audio amp present on the logic board via the ribbon cable.</p>
<h3 id="the-logic-board">The Logic Board</h3>
<p><img src="/images/GBDMG/Logic_Board_In_Case.jpg" alt="Logic board mounted in the case, showing all 3 boards" />
<a href="/images/GBDMG/originals/Logic_Board_In_Case.jpg">Logic board mounted in the case, showing all 3 boards</a></p>
<p><img src="/images/GBDMG/Logic_Board.jpg" alt="Logic board and attached daughter boards" />
<a href="/images/GBDMG/originals/Logic_Board.jpg">Logic board and attached daughter boards</a></p>
<p>Board Labels: <code class="language-plaintext highlighter-rouge">4-DA216</code>, <code class="language-plaintext highlighter-rouge">© 1989 Nintendo</code>, <code class="language-plaintext highlighter-rouge">DMG-CPU-03</code></p>
<p>The back of the case has 3 separate PCBs nestled inside of it:</p>
<ul>
<li>Logic board</li>
<li>DV converter daughter board</li>
<li>Headphone port daughter board</li>
</ul>
<p>The power and headphone boards are each separately connected to the logic board via 4 wires that attach to the bottom and side.
At both ends of the wires theres a small piece of plastic melted on that keeps the ends correctly spaced apart for attaching to the boards when being soldered by hand.</p>
<p>This board is attached to the case back directly with only two screws, though the four external screws also hold it in place.
The front of the board is where the majority of components are attached.
The back contains traces, the ribbon connector, and a copper pad.
The copper pad lines up with the chips on the front, and probably acts as heat sink.
This is also where <code class="language-plaintext highlighter-rouge">005.22</code> is stamped, matching the stamp on the screen board.
On my PCB, there is also a single fingerprint on the copper, probably from the person soldering the final parts on the board.</p>
<p>When mounted, the board has a good air gap between the chips and the back of the cartridge slot.
There is no heat sink directly on the chips, but the air gap paired with a metal plate attached to the cartridge slot on the case help dissipate heat and give the case a bit more strength.</p>
<p>One of the first thing I noticed with this board was the how it smells like an old PCB, similar to an old Commodore or Atari 400.
It looks as if most components on the board were attached using automated assembly lines, but some look like they were soldered by hand, due to some solder flux remaining on the board:</p>
<ul>
<li>Copper heat shield</li>
<li>Audio and power board connections</li>
<li>Power switch</li>
<li>Power jack</li>
<li>Battery terminals</li>
<li>Volume knob</li>
<li>Communication port</li>
<li>Ribbon connector</li>
<li>Cartridge slot</li>
</ul>
<p>The PCB is very square, measuring and 3 sides of the board have “rough edges”, meaning they were connected to each other in columns two PCBs wide when the PCB’s were being printed and assembled.</p>
<p><img src="/images/GBDMG/Logic_IC_Closeup.jpg" alt="Closeup of main chips" />
<a href="/images/GBDMG/originals/Logic_IC_Closeup.jpg">Closeup of main chips</a></p>
<p>There are 4 chips and a crystal mounted:</p>
<table>
<thead>
<tr>
<th>ID</th>
<th>Purpose</th>
<th>Chip Label</th>
<th>Board Label</th>
<th>Manufacturer</th>
</tr>
</thead>
<tbody>
<tr>
<td>U1</td>
<td>Processor</td>
<td>DMG-CPU B<br />© 1989 Nintendo<br />Japan<br />9017 W</td>
<td>DMG CPU</td>
<td>Sharp</td>
</tr>
<tr>
<td>U2</td>
<td>64Kb VRAM</td>
<td>LH5264TN-L<br />Sharp<br />Japan<br />9017 1 Y</td>
<td>64K SRAM</td>
<td>Sharp</td>
</tr>
<tr>
<td>U3</td>
<td>64Kb SRAM</td>
<td>LH5264TN-L<br />Sharp<br />Japan<br />9017 1 Y</td>
<td>64K S-RAM</td>
<td>Sharp</td>
</tr>
<tr>
<td>U4</td>
<td>Audio amp</td>
<td>DMG-AMP<br />IR3R40<br />9016 A</td>
<td>AMP</td>
<td>Sharp</td>
</tr>
<tr>
<td>X1</td>
<td>Crystal</td>
<td>D419C0</td>
<td>4.194304MHz</td>
<td>Daishinku</td>
</tr>
</tbody>
</table>
<h4 id="dmg-processor">DMG Processor</h4>
<p>The DMG does most of the heavy lifting, it is directly connected to most things on the board, including the VRAM, SRAM, cartridge socket, audio amp, I/O buttons, front screen, and external link port.
It is a sort of hybrid of the Intel 8080 and Zilog Z80 processors, a Sharp LR35902.
It adopts the instruction syntax from the Zilog, but much of the instruction set from the 8080.
The DMG also adopted a single address space and didn’t contain extended addressing modes beyond 8-bits.
It also meant that instead of having special instructions to access I/O input, it read their states from special places of mapped memory.
More can be found here about their similarities and differences: <a href="https://gbdev.gg8.se/wiki/articles/CPU_Comparision_with_Z80">https://gbdev.gg8.se/wiki/articles/CPU_Comparision_with_Z80</a>.</p>
<h4 id="vram">VRAM</h4>
<p>The video RAM chip is down and to the right from DMG chip.
It is connected via some address lines, some data lines, and read/write latches.
When writing data to the screen, the DMG will access this memory and send it to the screen, with the data routing back through the DMG chip to the screen.
As it reads and sends pixel data, the DMG will also manage the screen itself, including clock signal, horizontal sync and vertical sync.</p>
<h4 id="sram">SRAM</h4>
<p>The SRAM is located directly to the right of the DMG.
It is the working RAM for use by the game.
It is connected in a similar way as the VRAM, just to it’s own set of pins on the DMG processor.</p>
<h4 id="cartridge-slot">Cartridge Slot</h4>
<p>The cartridge slot is connected to many of the same pins as the SRAM.
The DMG choosing which device to operate on by setting either the write or read pin for the device.
This ensures that the DMG doesn’t accidentally attempt to read from both at the same time, which would surely result in garbage data being read or possibly an attempted double write of some sort.</p>
<h4 id="audio-amp">Audio Amp</h4>
<p>The audio amp manages the audio output.
It is connected to the DMG chip by two lines, carrying the left and right audio.
Volume knob is on other side of board, and is connected to the same two audio lines.
This means that the volume knob adjusts the volume before it enters the audio amp chip.</p>
<h4 id="io">I/O</h4>
<p>I/O is read via 6 pins, 4 input and 2 output.</p>
<p><img src="/images/GBDMG/IO_Diagram.JPG" alt="Diagram of the I/O circuit" />
<a href="https://gbdev.gg8.se/wiki/images/0/03/Gameboy1-cpuboard.gif">Diagram of the I/O circuit</a></p>
<p>The P14 and P15 pins are outputs, and P10, P11, P12, and P13 are inputs.
Between the output pins and each button is a diode, which ensures current doesn’t leak.</p>
<p>To read the buttons, the DMG will first set one of the output pins high and read each of the input pins.
If both P14 and P15 are high, the DMG would be unable to tell if the D-Pad was being pressed or one of the other buttons.
When fetching the states of the A, B, Select and Start buttons it will set P15 high, and to read the D-Pad it will set P14 high.
Once the pin is set, it will read the output of P10-P13 and stores it in the I/O register for use reference by the game.</p>
<h4 id="external-link-port">External Link Port</h4>
<p>The external link port is a 6 pin port mounted to the right of the DMG.
The first amd last pins are power and ground, while the remaining 4 consist of 2 output, 1 input, and 1 unused.
The are wired almost directly to the DMG, with only a resistor in the way.
Pins 2 and 3 are the I/O pins, with pin 2 sending data and pin 3 receiving data.
Pin 4 is not used.
Pin 5 is the clock signal, and is able to both send and receive the signal, depending on if the Gameboy is the master of the connected systems.</p>
<h4 id="more-on-the-board">More on the Board</h4>
<p>One thing that caught my eye on the PCB was a set of 6 unused, soldered over holes that looked almost like test points.
The are located at the top of the board, directly above the left side of the DMG processor.
Of the holes, 3 are grounded and aren’t connected to anything else.
The other 3 are connected to both the cpu and the screen ribbon connector port.
On the CPU, it connects to Data1 (pin 50), Data0 (pin 51), and clock (pin 53), all of them output pins.
I thought it might be like the external link port, but the Data1 and Data0 pins are outputs only; the external link port also has 6 pins, but it has dedicated input and output lines.
I also suspected it may have been a rudimentary IR port, which was present on the Gameboy Color, but the Gameboy color uses 4 pins for the infrared communication, so I still don’t know the purpose of these points.</p>
<h3 id="dc-converter-board">DC Converter Board</h3>
<p><img src="/images/GBDMG/DC_Conv_Front.jpg" alt="DC converter board front" />
<a href="/images/GBDMG/originals/DC_Conv_Front.jpg">DC converter board front</a></p>
<p><img src="/images/GBDMG/DC_Conv_Bottom.jpg" alt="DC converter board back" />
<a href="/images/GBDMG/originals/DC_Conv_Bottom.jpg">DC converter board back</a></p>
<p>Board Labels: <code class="language-plaintext highlighter-rouge">ALPS</code>, <code class="language-plaintext highlighter-rouge">VCC</code>, <code class="language-plaintext highlighter-rouge">G</code>, <code class="language-plaintext highlighter-rouge">DC</code>, <code class="language-plaintext highlighter-rouge">CONV</code>, <code class="language-plaintext highlighter-rouge">DMG</code></p>
<p>This power board attaches to the logic board via 4 wires, 1 read and 3 green.
It takes the +6V input from either the battery or mains and converts it to +5V for all the logic and -19V for the screen.</p>
<p>This board fits sideways in a space between the battery compartment and the side of the case.</p>
<h3 id="audio-jack-board">Audio Jack Board</h3>
<p><img src="/images/GBDMG/Audio_Jack_Front.jpg" alt="Audio jack PCB front" />
<a href="/images/GBDMG/Audio_Jack_Front.jpg">Audio jack PCB front</a></p>
<p><img src="/images/GBDMG/Audio_Jack_Back.jpg" alt="Audio jack PCB back" />
<a href="/images/GBDMG/originals/Audio_Jack_Back.jpg">Audio jack PCB back</a></p>
<p>Board Labels: <code class="language-plaintext highlighter-rouge">©1989 Nintendo</code>, <code class="language-plaintext highlighter-rouge">DMG Jack 03</code></p>
<p>This board is attached directly to the case with two screws.
It is a very simple board, only containing 3 inductors, 2 capacitors, and the audio jack.
It provides stereo sound (take that, Gameboy SP!).</p>
<p>It acts as a breakout board, all the heavy lifting is done on the logic board through the audio amp.
The components on it are there to regulate the output and protect the logic board from damage, in case someone connects a headphone jack to some charge.</p>
<hr />
<h2 id="conclusion">Conclusion</h2>
<p>The original Gameboy DMG truly began Nintendo’s line of modern handheld gaming consoles.
With it’s tiny screen and 4 colors it opened up a new world of games to millions of people around the world.
It has become a lasting cultural icon and was the host of many games I lovingly look back on, like Pokemon Blue, Super Mario Land and Tetris.</p>
<p>Today the easiest way to revisit this console is through emulators or the “Virtual Console” system in later Nintendo consoles.
Despite this, there is still something special to loading in some new AA batteries, popping in a game cart and tuning the contrast before setting in for some good old olive green gaming.</p>
<hr />
<h2 id="further-reading">Further Reading</h2>
<p>Official technical data: <a href="https://www.nintendo.co.uk/Support/Game-Boy-Pocket-Color/Product-information/Technical-data/Technical-data-619585.html">https://www.nintendo.co.uk/Support/Game-Boy-Pocket-Color/Product-information/Technical-data/Technical-data-619585.html</a></p>
<p>List of various parts and add-ons: <a href="https://maru-chang.com/hard/gb/english.htm#DMG">https://maru-chang.com/hard/gb/english.htm#DMG</a></p>
<p>Logic board PCB scans and schematic images: <a href="https://chipmusic.org/forums/topic/13608/dmg-main-board-schematic-circuit-arduinoboy/">https://chipmusic.org/forums/topic/13608/dmg-main-board-schematic-circuit-arduinoboy/</a></p>
<p>Schematic diagrams of all PCBs: <a href="https://gbdev.gg8.se/wiki/articles/DMG_Schematics">https://gbdev.gg8.se/wiki/articles/DMG_Schematics</a></p>
<p>Eagle PCB schematics files: <a href="https://gbdev.gg8.se/files/schematics/DMG-Rolf/">https://gbdev.gg8.se/files/schematics/DMG-Rolf/</a></p>
<p>External connector: <a href="http://www.hardwarebook.info/Game_Boy_Link">http://www.hardwarebook.info/Game_Boy_Link</a></p>Brendan ByersIcebergByers@protonmail.comThe original Gameboy DMG truly began Nintendo's line of modern handheld gaming consoles. With it's tiny screen and 4 colors it opened up a new world of games to millions of people around the world.My Tmux Setup2019-10-21T00:00:00+00:002019-10-21T00:00:00+00:00https://b13rg.github.io/Tmux-Setup<p>Tmux is a “Terminal Multiplexer”, meaning you can create and use multiple terminals in one window at the same time.
It can be extensively customized and there are tons of examples of configurations posted all over the place.</p>
<p>My configuration lives in my <a href="https://github.com/B13rg/configuration">configuration github repo</a>.
In the tmux folder, you’ll find two config files names <code class="language-plaintext highlighter-rouge">tmux.conf</code> and <code class="language-plaintext highlighter-rouge">tmux.remote.conf</code>.
The regular configuration is for the local computer, while the remote conf is for servers you remote into and start a tmux session on (usually through ssh).
The remote session has a few less lines, and a different prefix.</p>
<h2 id="copying-and-pasting-with-wsl">Copying and pasting with WSL</h2>
<p>One issue I ran into with tmux was running it on WSL.
It can be difficult to setup each so you can easily copy and paste within tmux and externally.</p>
<p>Set WSL to use <code class="language-plaintext highlighter-rouge">Ctrl+Shift+C/V</code> as Copy/Paste in the options tab of wSL settings.
To select text within the terminal to copy externally, hold</p>
<p>To select text to copy into windows, you’ll want to hold either <code class="language-plaintext highlighter-rouge">shift</code> or <code class="language-plaintext highlighter-rouge">alt+shift</code>.
Holding <code class="language-plaintext highlighter-rouge">shift</code> will select line by line of the WSL window.
I only use this mode when I have a single panel in view.
If there are multiple panels, it ignore the boundaries.</p>
<p><img src="/images/tmux/lineSelect.PNG" alt="Selecting holding `shift`" width="700px" /></p>
<p>If you have multiple panels open, <code class="language-plaintext highlighter-rouge">alt+shift</code> will select a rectangle instead of line by line.
Once the text you want is selected, press <code class="language-plaintext highlighter-rouge">enter</code> to add it to your windows clipboard.
If you select text accidentally, press <code class="language-plaintext highlighter-rouge">escape</code> before trying to select again or else it will select from the original selection start to where you click.</p>
<p><img src="/images/tmux/squareSelect.PNG" alt="Selecting holding `alt+shift`" /></p>
<p>To copy text to the tmux clipboard, you’ll simply select the text with the mouse without holding any keys down.
You can view the list of things you’ve copied by pressing <code class="language-plaintext highlighter-rouge">prefix+=</code>.
Then you can select which thing to insert at the cursor.</p>
<p><img src="/images/tmux/tmuxSelect.PNG" alt="Selecting text for tmux" /></p>
<h2 id="commands">Commands</h2>
<p>Quick list:</p>
<ul>
<li>Prefix is <code class="language-plaintext highlighter-rouge">alt+z</code></li>
<li><code class="language-plaintext highlighter-rouge">prefix+R</code>: Reload configuration</li>
<li><code class="language-plaintext highlighter-rouge">prefix+r</code>: Redraw window</li>
<li><code class="language-plaintext highlighter-rouge">shift+arrow</code>: Switch windows</li>
<li><code class="language-plaintext highlighter-rouge">prefix+S</code>: Open new window from session template</li>
<li><code class="language-plaintext highlighter-rouge">alt+arrow</code>: Switch panes</li>
<li><code class="language-plaintext highlighter-rouge">prefix+z</code>: Zoom in current pane</li>
<li><code class="language-plaintext highlighter-rouge">prefix+-</code>: Horizontal split current pane</li>
<li><code class="language-plaintext highlighter-rouge">prefix+|</code>: Vertically split current pane</li>
<li><code class="language-plaintext highlighter-rouge">prefix+=</code>: Open tmux clipboard</li>
</ul>
<hr />
<p>These commands are all set in the <code class="language-plaintext highlighter-rouge">.tmux.conf</code> file present in my <code class="language-plaintext highlighter-rouge">$HOME</code> directory.</p>
<p>When making changes and customizing tmux, it is useful to be able to easily reload the configuration when you make changes.
To do this, I use the bind <code class="language-plaintext highlighter-rouge">bind R source-file ~/.tmux.conf</code>.</p>
<p>The first command I reset was the prefix key.
By default, it is set to <code class="language-plaintext highlighter-rouge">alt+b</code>, which is quite a stretch to reach.
I set my local tmux prefix to <code class="language-plaintext highlighter-rouge">alt+z</code> and the remote to <code class="language-plaintext highlighter-rouge">alt+x</code>.
This allows me to differentiate between the tmux session running locally or the tmux session nested within an ssh session on another server.
Additionally, <code class="language-plaintext highlighter-rouge">alt+z</code> is much easier and quicker to hit that the default.
The configuration code:</p>
<pre><code class="language-txt">set -g prefix M-z
unbind C-b
bind M-z send-prefix
</code></pre>
<p>One command I use often is zoom.
<code class="language-plaintext highlighter-rouge">prefix+z</code> takes the current pane and full screens it.
It’s useful for when you want to take a closer look at some output that smooshes just the wrong way when sequestered in a pane.</p>
<p>Moving between panes and windows quickly is important.
The default configuration can be difficult to remember, and not intuitive.
To switch between panes, I use <code class="language-plaintext highlighter-rouge">alt+arrow</code>.
It’s also set so there is no need to push the <code class="language-plaintext highlighter-rouge">alt+z</code> prefix key to switch.</p>
<pre><code class="language-txt"># Use alt+arrows to switch between panes
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
</code></pre>
<p>To switch between windows, I use <code class="language-plaintext highlighter-rouge">shift+arrow</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Use shift+lft/right to switch between windows
bind -n S-Left previous-window
bind -n S-Right next-window
</code></pre></div></div>
<p>To create additional panes, I modified the commands to use <code class="language-plaintext highlighter-rouge">-</code> and <code class="language-plaintext highlighter-rouge">|</code> to split horizontally and vertically.
Additionally, all pane creation is done with the right hand instead of different hands doing different splits.</p>
<pre><code class="language-txt">bind | split-window -h
bind - split-window -v
</code></pre>
<p>Having pre-configured windows that have a custom setup can be useful.
Once you create the file configuring the session, you can place it in a directory and bind a host key to automatically open it.
In my case, I use <code class="language-plaintext highlighter-rouge">bind S source-file ~/.tmux/session1</code>, which opens a custom view in a new window.</p>
<h3 id="other-settings">Other settings:</h3>
<ul>
<li><code class="language-plaintext highlighter-rouge">set -g base-index 1</code>: Starts window numbering from 1, because 0 is on the other side of the keyboard.</li>
<li><code class="language-plaintext highlighter-rouge">set -g mouse on</code>:This allows me to use the mouse to do things like resize windows, select text, and click between panels.</li>
<li><code class="language-plaintext highlighter-rouge">set -sg escape-time 0</code>: Stop having to wait to press esc twice when canceling things.</li>
<li><code class="language-plaintext highlighter-rouge">set -g history-limit 10000</code>: Scrolling remembers 10,000 lines.</li>
<li><code class="language-plaintext highlighter-rouge">setw -g mode-keys vi</code>: Set mode to vi instead of emacs.</li>
</ul>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="http://man7.org/linux/man-pages/man1/tmux.1.html">Tmux man page</a></li>
<li><a href="https://tmuxcheatsheet.com/">Cheatsheet</a></li>
<li><a href="https://gist.github.com/search?o=desc&q=tmux.conf&s=stars">Examples of other tmux.conf</a></li>
</ul>Brendan ByersIcebergByers@protonmail.comTmux is a "Terminal Multiplexer", meaning you can create and use multiple terminals in one window at the same time. This article describes the various customizations I have made to make my life in the terminal easier.Gameboy DMG ROM and RAM Bank Switching2019-07-22T00:00:00+00:002019-07-22T00:00:00+00:00https://b13rg.github.io/Gameboy-Bank-Switching<p>Bank switching is a method of switching what data is accessible by a program.
It was used to allow a CPU with a static memory map the ability to address additional data than what would usually be able to be addressed.
The original Gameboy DMG used a CPU similar to the Zilog Z-80.
It used a 16 bit address bus, allowing it to access up to 2^16 bytes (<code class="language-plaintext highlighter-rouge">$0000-$FFFF</code>).
Here is an image of the memory map for the Gameboy, sourced from <a href="https://problemkaputt.de/pandocs.htm">Pan Docs</a>.</p>
<p><img src="/images/GameboyBankSwitching/memoryMap.PNG" alt="Memory Map" /></p>
<p>ROM and RAM bank switching is controlled by a memory bank controller present on the cartridge.
By writing values to areas of read-only memory, a game or program is able to specify which ROM banks to access when read operations are performed.</p>
<p>The simplest cartridges simply contained ROM and had only had 32 KBytes of space.
It is mapped directly to <code class="language-plaintext highlighter-rouge">$0000-$7FFF</code>.
There was no MBC on these types of cartridges because the entire game would be able to fit on the cartridge.
This types of cartridge could also contain up to 8KB of RAM, mapped to <code class="language-plaintext highlighter-rouge">$A000-$BFFF</code>, though it would require an MBC-like circuit to work.</p>
<p><img src="/images/GameboyBankSwitching/TetrisCart.jpg" alt="Tetris Cart" /></p>
<p>An example of a game that didn’t use a MBC was Tetris, whose ROM is only 19KB.
The game was small enough that no bank
We can see here how simple the game cartridge is, only requiring the ROM chip with the game code.
<a href="https://gbhwdb.gekkio.fi/cartridges/DMG-TRA-1/gekkio-1.html">Cart Information</a></p>
<p>Larger games required larger amounts of storage which the Gameboy was not natively able to address.
Bank switching is the solution to this.</p>
<p>Cartridges needing additional capabilities had a lot more going on than Tetris.
Instead of data lines connecting directly to the ROM, they instead go through a memory bank controller that manages manages the bank switching of the ROM and RAM through intercepting read and write commands to certain addresses.</p>
<h2 id="types-of-memory-bank-controllers">Types of Memory Bank Controllers</h2>
<p>There were 4 (and a half) types of MBCs that cartridges used.
They each possessed different amounts of ROM and RAM.
Each ROM bank was 16KB in size</p>
<ul>
<li>MBC1: max 2MB ROM (125 banks) and/or up to 32KB RAM</li>
<li>MBC2: max 256KB ROM (16 banks) and 512x4 bits RAM</li>
<li>MBC3: max 2MB ROM (128 banks) and/or 32KB RAM (4 banks) and Timer</li>
<li>MBC5: max 8MB ROM (512 banks) and/or 128KB RAM (16 banks)</li>
<li>HuC1: Similar to MBC1 with an Infrared Controller</li>
</ul>
<p>One thing to note is that MBC1 and MBC3 both support 2MB, but have a different number of banks (125 vs. 128).
I will explain that once I explain the memory map and bank switching.
In this article, I primarily focus on explaining how the MBC1 works.</p>
<h2 id="mbc1-memory-map">MBC1 Memory Map</h2>
<p>This was the first MBC chip for the Gameboy.
It behaves much the same as the other, with a few exceptions.
A cartridge with an MBC1 uses to following memory ranges:</p>
<p><strong><code class="language-plaintext highlighter-rouge">$0000-$3FFF</code>: ROM Bank <code class="language-plaintext highlighter-rouge">$00</code> (Read Only)</strong></p>
<p>This always contains the first 16KB of the cartridge, the first memory bank.
It is unable to be switched or modified.</p>
<p><strong><code class="language-plaintext highlighter-rouge">$4000-$7FFF</code>: Additional ROM Banks (Read Only)</strong></p>
<p>This area of memory will contain whatever memory bank is currently selected.</p>
<p><strong><code class="language-plaintext highlighter-rouge">$A000-$BFFF</code>: Ram Bank, if present (Read/Write)</strong></p>
<p>This is where RAM banks will be placed in memory.
They are able to be both written to and read from, allowing the game to store data.
If the cartridge contains a battery, like in Pokemon cartridges, the data written is able to be preserved across shutdowns.
This type of MBC had 3 different RAM options:</p>
<ul>
<li>2KB: <code class="language-plaintext highlighter-rouge">$A000-A7FF</code></li>
<li>8KB: <code class="language-plaintext highlighter-rouge">$A000-BFFF</code></li>
<li>32KB: <code class="language-plaintext highlighter-rouge">$A000-BFFF</code> (four switchable 8KB banks)</li>
</ul>
<p><strong><code class="language-plaintext highlighter-rouge">$0000-$1FFF</code>: RAM Enable (Write Only)</strong></p>
<p>Before a game is able to use the RAM, it must be specifically enabled.
This is done by writing a value with the lower 4 bits being <code class="language-plaintext highlighter-rouge">$0A</code> somewhere in this address space.
To disable RAM, any number except <code class="language-plaintext highlighter-rouge">$0A</code> can be written.
It does not matter where it is written, just as long as it within the address range.
You will notice that this address range is part of the first ROM bank, which is read only.
Because it is ROM, there is obviously no way to actually write data to those memory locations.
Instead, the write call is “intercepted” and interpreted differently by the MBC.
This method of writing to ROM is also used for the remaining memory areas I’ll explain now.</p>
<p><strong><code class="language-plaintext highlighter-rouge">$2000-$3FFF</code>: ROM Bank Number (Write Only)</strong></p>
<p>Writing a value to this address range will select the lower 5 bits of the bank number.
There are a few special cases though.
If the value <code class="language-plaintext highlighter-rouge">$00</code> is written, it will converted to bank <code class="language-plaintext highlighter-rouge">$01</code>.
This is not an issue because bank <code class="language-plaintext highlighter-rouge">$00</code> is always present at <code class="language-plaintext highlighter-rouge">$0000-$3FFF</code>.
The issue lies in writing the values <code class="language-plaintext highlighter-rouge">$20</code>, <code class="language-plaintext highlighter-rouge">$40</code>, and <code class="language-plaintext highlighter-rouge">$60</code>.
When these values are written, instead of addressing the correct ROM banks they will address banks <code class="language-plaintext highlighter-rouge">$21</code><code class="language-plaintext highlighter-rouge">$41</code> and <code class="language-plaintext highlighter-rouge">$61</code> respectively.
I couldn’t find an explanation of why this takes place, but I assume it has something to do with how the lower 5 bits are used when choosing the bank.
Each of these numbers have all zeros as the lower 5 bits (<code class="language-plaintext highlighter-rouge">0x0XX</code><strong><code class="language-plaintext highlighter-rouge">00000</code></strong>).
This issue is not present in MBC2 and MBC3.</p>
<p><strong><code class="language-plaintext highlighter-rouge">$6000-$7FFF</code>: ROM/RAM Mode Select (Write Only)</strong></p>
<p>Writing either <code class="language-plaintext highlighter-rouge">$00</code> or <code class="language-plaintext highlighter-rouge">$01</code> to this area will select which mode the MBC is in.
On an MBC1, there are two modes: 16Mb ROM/8KB RAM and 4Mb ROM/32KB RAM.
The game is able to switch between the modes on the fly, allowing a game to access extended ROM banks during normal operation and switch to RAM mode temporarily when data needs to be read.
Valid values are <code class="language-plaintext highlighter-rouge">$00</code> for ROM mode and <code class="language-plaintext highlighter-rouge">$01</code> for RAM mode.</p>
<p><strong><code class="language-plaintext highlighter-rouge">$4000-$5FFF</code>: RAM Bank Number or Upper Bits of ROM Bank Number (Write Only)</strong></p>
<p>Writing to this area of memory will effect the ROM or RAM modes, depending on what is written in <code class="language-plaintext highlighter-rouge">$6000-$7FFF</code>.
Only the first two bits of the value matter.
If in ROM mode (no RAM bank switching), it will specify the upper two bits of the ROM bank number.
In this mode, only RAM bank <code class="language-plaintext highlighter-rouge">$00</code> may be used.</p>
<p>If in RAM mode, it will specify which RAM bank to load into <code class="language-plaintext highlighter-rouge">$A000-$BFFF</code>.
In this mode, only ROM banks <code class="language-plaintext highlighter-rouge">$00-$1f</code> may be used.</p>
<hr />
<p>The MBC1 is only able to switch between 125 different ROM banks, instead of the expected 128.
The ROM banks are addressed using a 6 bit number created from writing to <code class="language-plaintext highlighter-rouge">$2000-$3FFF</code> and <code class="language-plaintext highlighter-rouge">$4000-$5FFF</code>.
The reason is because of the number conversion when writing <code class="language-plaintext highlighter-rouge">$20</code>, <code class="language-plaintext highlighter-rouge">$40</code>, and <code class="language-plaintext highlighter-rouge">$60</code> to <code class="language-plaintext highlighter-rouge">$2000-$3FFF</code>.
This results in it being able to address 128-3 or 125 banks for a actual total of 1.95MB, not 2MB.
This issue is not present in MBC2 and MBC3.
MBC2 has a maximum of 16 banks, so the issue is never encountered.
The MBC3 chip correctly addresses <code class="language-plaintext highlighter-rouge">$20</code>, <code class="language-plaintext highlighter-rouge">$40</code>, and <code class="language-plaintext highlighter-rouge">$60</code> and does not perform the conversion.</p>
<h2 id="bank-switching-in-practice">Bank Switching in Practice</h2>
<p>That was a lot of numbers and memory ranges, so now I’ll give a few examples of bank switching and the process a game would take.</p>
<p>When the Gameboy is first turned on, the cartridge header is read and gives information on the ROM and RAM sizes present on the cartridge.
Byte <code class="language-plaintext highlighter-rouge">$0147</code> specifies the type of MBC and what hardware is present on the cart.
Byte <code class="language-plaintext highlighter-rouge">$0148</code> specifies the size of the ROM, from which the number of banks can be derived.
The next byte after, <code class="language-plaintext highlighter-rouge">$0149</code>, specifies the size of the RAM</p>
<p><img src="/images/GameboyBankSwitching/headerData.PNG" alt="Pokemon Blue Header" /></p>
<p>Looking at a compiled ROM of Pokemon Blue, we can see that the MBC type is <code class="language-plaintext highlighter-rouge">$13</code> and the ROM banking type is <code class="language-plaintext highlighter-rouge">$05</code>.
These values correspond to different hardware settings, which we can see by referencing the <a href="https://problemkaputt.de/pandocs.htm#thecartridgeheader">header definition</a>.
Looking these values up against the table, we can see that the MBC type is <code class="language-plaintext highlighter-rouge">MBC3+RAM+BATTERY1</code> and that there is 1MB of ROM, or 64 banks.
We can further verify this by checking the size of a dumped ROM, which is exactly 1024KB.
Finally, the RAM size value is <code class="language-plaintext highlighter-rouge">$03</code>, which corresponds to 32KB of RAM, 4 banks of 8KB.</p>
<p>We can further verify these values by looking at the actual hardware of Pokemon Blue.
Once again, we have the picture of the PCB of the game here:</p>
<p><img src="/images/GameboyBankSwitching/PokeBlueCart.jpg" alt="Pokemon Blue" /></p>
<p>The MBC chip, highlighted in purple, is labeled as an MBC3 chip.
Below that, we have the SRAM in blue, the the ROM chip is red to the right.
Since it has the MBC3, RAM chip and a battery, we can confirm that the MBC type value is correct.</p>
<p>The SRAM chip is a 256K LH52256CN-10LL (<a href="https://pdf1.alldatasheet.com/datasheet-pdf/view/42986/SHARP/LH52256CN-10LL.html">Datasheet</a>).
This is where the game save resides when the game is not being played.
This chip contains much more SRAM than the cartridge header specifies oddly enough.
I was unable to determine why.
The data is preserved in the chip by using the coin battery to make sure the SRAM always has power.
The RAM protector manages the power going into the SRAM from the battery, allowing the data to be preserved.
<a href="https://gbhwdb.gekkio.fi/cartridges/DMG-APEE-0/gekkio-1.html">Cart Information</a></p>
<p>The later generations of Pokemon (Gold/Silver/Crystal) were similarly designed, but suffered from battery issues sooner than Red and Blue.
This was because these games had an internal clock that kept the time.
You can see the pads where it would be soldered on the PCB above in the upper left corner.
This additional power draw meant that the battery needed to be replaced much sooner, resulting in saved data being lost.</p>
<hr />
<p>For these examples I used the Pokemon Red/Blue disassembly located on <a href="https://github.com/pret/pokered">Github</a>.
It is very well commented and not to difficult to follow along in the code.
Additionally, it is able to be compiled into a working copy of the game that is exactly the same as a real copy of the game ROM.
This makes it a good reference for how bank switching took place in practice.</p>
<h3 id="switching-to-a-rom-bank--20">Switching to a ROM Bank < <code class="language-plaintext highlighter-rouge">$20</code></h3>
<p>Switching to banks <code class="language-plaintext highlighter-rouge">$01-$1F</code> is very simple.
We only need to write our intended bank to <code class="language-plaintext highlighter-rouge">$2000-$3FFF</code>.
This example is located in <code class="language-plaintext highlighter-rouge">home\copy2.asm</code>, and copies data to a bank specified by the calling function.
Before switching banks, it stores the previous bank in <code class="language-plaintext highlighter-rouge">hROMBankTemp</code> and then performs the bank switch.</p>
<pre><code class="language-asm">; hardware_constants.asm: 7
MBC1RomBank EQU $2000
; hram.asm: 19
hROMBankTemp EQU $FF8B
; copy2.asm: FarCopyData2
ld [hROMBankTemp], a ; a is desired bank set by calling function
ld a, [H_LOADEDROMBANK] ; H_LOADEDROMBANK set by calling function
push af ; temporarily stores the current bank number
ld a, [hROMBankTemp] ; load the designated temp bank into a
ld [H_LOADEDROMBANK], a ; Load out selected ROM bank into memory
ld [MBC1RomBank], a ; switch to the bank described by register a
call CopyData
pop af ; restore what registers af were
ld [H_LOADEDROMBANK], a ; load the original bank number
ld [MBC1RomBank], a ; Switch back to the previous ROM bank
ret
</code></pre>
<h3 id="switching-to-a-rom-bank--1f">Switching to a ROM Bank > <code class="language-plaintext highlighter-rouge">$1F</code></h3>
<p>To switch to a ROM bank greater than <code class="language-plaintext highlighter-rouge">$1F</code>, there is some extra legwork to be done.
First, we need to switch to the ROM banking mode.
Then we write the lower 5 bits to <code class="language-plaintext highlighter-rouge">$2000-$3FFF</code> and the upper 2 bits to <code class="language-plaintext highlighter-rouge">$4000-$5FFF</code>.
For this example, I will be loading bank <code class="language-plaintext highlighter-rouge">$46</code>.
Because Pokemon Blue only had 64 banks, there was no need to perform this type of bankswitch.
Instead, I took the previous bankswitching code and modified it slightly.
To get the first 5 bits, I perform an <code class="language-plaintext highlighter-rouge">and</code> with <code class="language-plaintext highlighter-rouge">$1f</code> (<code class="language-plaintext highlighter-rouge">0x0001 0x1111</code>).
The get the upper two bits, I perform a logical shift right to get them in the correct position to <code class="language-plaintext highlighter-rouge">and</code> it with <code class="language-plaintext highlighter-rouge">$3</code> (<code class="language-plaintext highlighter-rouge">0x0011</code>).</p>
<pre><code class="language-asm">; hardware_constants.asm: 7
MBC1RomBank EQU $2000
MBC1SRamBankingMode EQU $6000
MBC1SRamBank EQU $4000
; hram.asm: 19
hROMBankTemp EQU $FF8B
ld [H_LOADEDROMBANK], $46 ; Pretend we are the calling function
ld [hROMBankTemp], a ; a is desired bank set by calling function
ld a, [H_LOADEDROMBANK] ; H_LOADEDROMBANK set by calling function
push af ; temporarily stores the current bank number
ld a, [hROMBankTemp] ; load the designated temp bank into a
ld [MBC1SRamBankingMode], $0 ; Switch to ROM mode
ld [H_LOADEDROMBANK], a ; Save our selected ROM bank into memory
; start of my code
ld b, a ; Use b as a temp register
and $1F ; Keep the lower 5 bits
ld [MBC1RomBank], b ; Set the lower 5 bits of our desired bank
ld a, b ; Load b into a once again
rrca ; Rotate right 5 times to move
rrca ; bits 6 and 7 into position
rrca
rrca
rrca
and $3 ; Mask out the rest of the bits in a
ld [MBC1SRamBank], a ; pass in the upper two bits
; End of my added code
call CopyData
pop af ; restore what registers af were
ld [H_LOADEDROMBANK], a ; load the original bank number
ld [MBC1RomBank], a ; Switch back to the previous ROM bank
ret
</code></pre>
<h3 id="reading-data-from-ram">Reading Data from RAM</h3>
<p>To read a value from a RAM bank other than <code class="language-plaintext highlighter-rouge">$00</code>, we need to switch to RAM mode.
First the RAM is enabled.
After each use, it is disabled once again to protect the data.
Next, the game switches from ROM mode to RAM mode.
This enables us to access data in RAM.
Finally, we write what RAM bank we want to access to.
In this case, it is bank <code class="language-plaintext highlighter-rouge">$1</code>.
Once this is done, we can begin moving data in and out of the RAM.
After working with the RAM, it is once again disabled and switched back to ROM mode.
It is important to disable RAM once you’re done with it because if there is an unexpected shutdown, it can leave the RAM in an inconsistent state.</p>
<p>This code example is located in <code class="language-plaintext highlighter-rouge">engine\menu\main_menu.asm</code> and is used to search for the player’s name in RAM.</p>
<pre><code class="language-asm">; hardware_constants.asm: Line 6
MBC1SRamEnable EQU $0000
MBC1SRamBank EQU $4000
MBC1SRamBankingMode EQU $6000
SRAM_DISABLE EQU $00
SRAM_ENABLE EQU $0a
; main_menu.asm: Function CheckForPlayerNameInSRAM
ld a, SRAM_ENABLE ; Load the SRAM enable value into register a
ld [MBC1SRamEnable], a ; Enable the ram
ld a, $1
ld [MBC1SRamBankingMode], a ; Switch to RAM mode
ld [MBC1SRamBank], a ; Select RAM bank 1
; ...
; Searches through SRAM for player's name here
; ...
xor a ; set register a to 0
ld [MBC1SRamEnable], a ; Disable the RAM
ld [MBC1SRamBankingMode], a ; Switch back to ROM mode
and a ; used to reset carry flag
ret
</code></pre>
<h2 id="further-reading">Further Reading</h2>
<p><a href="https://problemkaputt.de/pandocs.htm#memorybankcontrollers">Pan Docs</a></p>
<p><a href="http://gbdev.gg8.se/wiki/articles/Memory_Bank_Controllers">GB Dev Wiki: Memory Bank Controllers</a></p>
<p><a href="http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf">Gameboy CPU Manual</a>
<a href="https://gitlab.com/InfiniteNesLives/INL-retro-progdump/-/issues/59#note_461096509">Example of bank switching used in ROM dumping script</a></p>Brendan ByersIcebergByers@protonmail.comThe original Gameboy DMG used a CPU similar to the Zilog Z-80. It utilized bank switching to allow the CPU, with a static memory map, the ability to address additional data than what would usually be able to be addressed.Simple Ansible Project2019-05-15T00:00:00+00:002019-05-15T00:00:00+00:00https://b13rg.github.io/Ansible-Setup<p><a href="https://www.ansible.com/">Ansible</a> makes deployment of software and configuration to multiple servers easy.
A deployment process is described in a yaml file and is used by Ansible as instructions for what to do.
In this article, I describe the process of deploying a simplt html file to multiple servers and have each of them serve the file using apache.
To make it easy, virtual machines were used for everything.
My setup consisted of 6 different VMs:</p>
<ul>
<li>1 pfSense VM for network routing</li>
<li>1 Centos CLI VM to act as the controller</li>
<li>4 Alpine Linux VMs to act as nodes</li>
</ul>
<p>Files for this project can be found in my <a href="https://github.com/B13rg/Projects/tree/master/Ansible%20Example">Project repository</a> in the <code class="language-plaintext highlighter-rouge">Ansible Example</code> folder. I only included the alpine VM because centos and pfsense are a little heavy.</p>
<p>Also included in the repository is the <code class="language-plaintext highlighter-rouge">index.html</code> file I serve, the <code class="language-plaintext highlighter-rouge">hosts</code> file I used for Ansible, and <code class="language-plaintext highlighter-rouge">WebServ.yaml</code> that ansible-playbook uses to deploy the project.</p>
<h2 id="configuring-the-virtual-machines">Configuring the Virtual Machines</h2>
<p>First the pfSense VM is started up.
This will provide the networking between the different VM’s.
In the network settings of the VM, Adapter 1 should be attached to <code class="language-plaintext highlighter-rouge">NAT</code> and Adapter 2 attached to <code class="language-plaintext highlighter-rouge">Internal Network</code>.
This internal network is how the rest of the VMs will be connecting to each other.</p>
<p>Once the router has started,the Alpine VMs and the Centos “controller” VM can be started.
Once everything has booted up and is ready to go, we will need to make sure the controller VM is able to access and log into each of the alpine VMs.</p>
<p>To do that we first need to share the controller’s <code class="language-plaintext highlighter-rouge">id_rsa</code> file with each of the alpine VM’s.
If the <code class="language-plaintext highlighter-rouge">id_rsa</code> file doesn’t exist, it can create it with the command <code class="language-plaintext highlighter-rouge">ssh-keygen -t rsa</code>.
Copying the id file to a target VM can be done with the command <code class="language-plaintext highlighter-rouge">ssh-copy-id -i ~/.ssh/id_rsa root@192.168.1.xx</code>, where <code class="language-plaintext highlighter-rouge">root@192.168.1.xx</code> is replaced with the username and IP of the target VM.
The password for the server will also need to typed in so the file can be copied over.
In my case, I have 4 alpine VMs running at:</p>
<ul>
<li>192.168.1.21</li>
<li>192.168.1.22</li>
<li>192.168.1.23</li>
<li>192.168.1.24</li>
</ul>
<p>Once the <code class="language-plaintext highlighter-rouge">rsa_id</code> is distributed to each of the VMs, the controller should be able to ssh into each of them without needing to enter a password.
This enables Ansible to access each of them without requiring a file with the passwords to be kept in plaintext somewhere.</p>
<p>Now that we are able to connect to each of the nodes, we will want to install Ansible and configure configure it to connect to the alpine VMs.</p>
<p>Once Ansible is installed, we want to add the alpine VMs to Ansible’s host file.
This file keeps a record of all the different machines Ansible can target assembled in groups.
This file is usually located in <code class="language-plaintext highlighter-rouge">/etc/ansible/hosts</code>.
for this project I grouped the alpine IPs in a collection named <code class="language-plaintext highlighter-rouge">alpiney</code>.
I define each of my nodes by listing out each ip, but I could also use <code class="language-plaintext highlighter-rouge">192.168.1.[21:24]</code>.</p>
<p><img src="/images/ansibleSetup/ansibleHosts.JPG" alt="List of hosts" /></p>
<p>In our playbook that tells Ansible what to do, we will use the collection name to refer to these ips.
This in done with the <code class="language-plaintext highlighter-rouge">hosts: alpiney</code> command in the playbook yaml.</p>
<h2 id="telling-ansible-what-to-do">Telling Ansible what to do</h2>
<p>The steps for the deployment are defined in a yaml file.
for this project, there are 4 primary tasks that need to take place:</p>
<ol>
<li>Install <code class="language-plaintext highlighter-rouge">apache2</code> on the node</li>
<li>Copy our <code class="language-plaintext highlighter-rouge">index.html</code> file to the node</li>
<li>Modify <code class="language-plaintext highlighter-rouge">index.html</code> with an Ansible variable</li>
<li>Make sure apache is running</li>
</ol>
<p>Installing <code class="language-plaintext highlighter-rouge">apache2</code> using Ansible is very straightforward.
We will use the <code class="language-plaintext highlighter-rouge">apk</code> module and define what package and what version of the package we want.
When this task is complete, apache will be installed and be in the default setup.
The yaml for this task till look like this:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install apache2</span>
<span class="na">apk</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">apache2</span>
<span class="na">state</span><span class="pi">:</span> <span class="s">latest</span>
</code></pre></div></div>
<p>Next, we want to copy our <code class="language-plaintext highlighter-rouge">index.html</code> webpage over to the nodes.
This is done using the <code class="language-plaintext highlighter-rouge">template</code> module, and requires specifying a source and destination (<code class="language-plaintext highlighter-rouge">src</code>,<code class="language-plaintext highlighter-rouge">dest</code>).
To find where to place the html file, I needed to look at the configuration of apache2 located in <code class="language-plaintext highlighter-rouge">/etc/apache2/httpd.conf</code> and look for the <code class="language-plaintext highlighter-rouge">DocumentRoot</code> entry.
In my case, it was located in <code class="language-plaintext highlighter-rouge">/var/www/localhost/htdocs</code>.
We will use this directory in our yaml file to direct Ansible where to place the <code class="language-plaintext highlighter-rouge">index.html</code> file.</p>
<p>When the file is copied, we will also want to restart the apache service so it sees the file properly.
To do this, we will use a handler.
A handler can be called after or before certain events.
In my script, i use a <code class="language-plaintext highlighter-rouge">notify</code> tag which will execute the handler once the task is complete.
The handler is defined separately from the task, we only need to call it!
The code for this task looks like:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">-name</span><span class="pi">:</span> <span class="s">Transfer index.html to node</span>
<span class="s">template</span><span class="pi">:</span>
<span class="na">src</span><span class="pi">:</span> <span class="s">index.html</span> <span class="c1"># File is in same directory</span>
<span class="na">dest</span><span class="pi">:</span> <span class="s">/var/www/localhost/htdocs/index.html</span>
<span class="na">notify</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">restart apache</span>
<span class="nn">...</span>
<span class="na">handlers</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">restart apache</span> <span class="c1"># Matches name under notify</span>
<span class="na">service</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">apache2</span>
<span class="na">state</span><span class="pi">:</span> <span class="s">restarted</span>
</code></pre></div></div>
<p>Now that the <code class="language-plaintext highlighter-rouge">index.html</code> file is present on the nodes, we only need to add our Ansible variable to the file and ensure apache is running.
For this task, I defined a variable named <code class="language-plaintext highlighter-rouge">template_run_date</code>, which grabs the time from Ansible like so:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">vars</span><span class="pi">:</span>
<span class="na">template_run_date</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ansible_facts['date_time']['iso8601_micro']</span><span class="nv"> </span><span class="s">}}"</span>
</code></pre></div></div>
<p>To show how to replace values in files, I did it two different ways.
The first (and better) way to insert runtime variables is be referencing the variable within the file using <code class="language-plaintext highlighter-rouge">{{ variable_name }}</code>.
In the <code class="language-plaintext highlighter-rouge">index.html</code> file, I added the line <code class="language-plaintext highlighter-rouge">{{ template_run_date }}</code>.
When Ansible is ran, it will fetch the variable and replace it in the file.
I could have also used the <code class="language-plaintext highlighter-rouge">ansible_facts</code> variable instead of defining my own.
For this method, the modifications take place within the file that wants the variable, not the playbook file.</p>
<p>Another method is to use the <code class="language-plaintext highlighter-rouge">replace</code> command and regex.
To make it easy, I placed the text <code class="language-plaintext highlighter-rouge">##repl##</code> in the <code class="language-plaintext highlighter-rouge">index.html</code> file.
It is easily targeted with the regex.
For the <code class="language-plaintext highlighter-rouge">replace</code> command, I specified the path of the file, the expression to evaluate, and the text to replace it with (<code class="language-plaintext highlighter-rouge">path</code>,<code class="language-plaintext highlighter-rouge">regexp</code>,<code class="language-plaintext highlighter-rouge">replace</code>).
The code to perform this in the playbook looks like:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">-name</span><span class="pi">:</span> <span class="s">Insert template_run_date variable</span>
<span class="na">replace</span><span class="pi">:</span>
<span class="na">path</span><span class="pi">:</span> <span class="s">/var/www/localhost/htdocs/index.html</span>
<span class="na">regexp</span><span class="pi">:</span> <span class="s1">'</span><span class="s">##repl##'</span>
<span class="na">replace</span><span class="pi">:</span> <span class="s1">'</span><span class="s">template_run_date</span><span class="nv"> </span><span class="s">val:</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">template_run_date</span><span class="nv"> </span><span class="s">}}'</span>
</code></pre></div></div>
<p>Our example <code class="language-plaintext highlighter-rouge">index.html</code> file is setup to show the variable using the inline method and the regex replacement method.
The full code for the html file is here:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>My Title<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
This is some text.
Inline replacement: {{template_run_date }}
Regex replacement: ##repl##
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>When the replacements take place, the replacement done using the task will be data a little bit later than placing the varaible directly in the file.
Replacing <code class="language-plaintext highlighter-rouge">{{ variable }}</code> in a file is done when the file is copied to a node.
The replace task takes place after the file transfer because it is a separate task.
Both of these actions take place node, by node so even though the same instructions are applied to all nodes the time it is applied will be different as you can see in this image:</p>
<p><img src="/images/ansibleSetup/inlineVsRegex.JPG" alt="Timstamps of different files" /></p>
<p>Once the file is on the server and properly modified, we will make sure apache is running.
This is just to make sure everything is seen correctly and apache is behaving.
If it is not running, it won’t be able to serve our <code class="language-plaintext highlighter-rouge">index.html</code> file (duh).
This is very simple, and is done using the following task:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Ensure Apache is running</span>
<span class="na">service</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">apache2</span>
<span class="na">state</span><span class="pi">:</span> <span class="s">started</span>
</code></pre></div></div>
<p>The complete yaml file can be found in the <a href="https://github.com/B13rg/Projects/blob/master/Ansible%20Example/WebServ.yaml">project repository</a>.</p>
<h2 id="deployment">Deployment</h2>
<p>Now that we have written our playbook and setup our <code class="language-plaintext highlighter-rouge">index.html</code> file, we now want to deploy.
We do this using the command <code class="language-plaintext highlighter-rouge">ansible-playbook <PB Name>.yaml</code>.
Ansible will now go through each task and perform it on each of the nodes.
Green text means the task was performed successfully.
Orange text means that the task completed successfully with some modifications taking place on the node.
Red text means there was an error.
Once it is complete, it will display a summary of what happened for each of the nodes.</p>
<p><img src="/images/ansibleSetup/recap.JPG" alt="Summary of the deployment" /></p>
<p>If everything was successful, our web page will now be available on each of our nodes we deployed to.
To check it, use the <code class="language-plaintext highlighter-rouge">curl</code> command.
It will return our <code class="language-plaintext highlighter-rouge">index.html</code> file with our replaced text.</p>
<p><img src="/images/ansibleSetup/curlResult.JPG" alt="Summary of the deployment" /></p>Brendan ByersIcebergByers@protonmail.comAnsible makes deployment of software and configuration to multiple servers easy. A deployment process is described in a yaml file and is used by Ansible as instructions for what to do. In this article, I describe the process of deploying a simplt html file to multiple servers and have each of them serve the file using apache. To make it easy, virtual machines were used for everything. My setup consisted of 6 different VMs:Checking out a 3COM 3C996B-T Gigabit NIC2019-05-10T00:00:00+00:002019-05-10T00:00:00+00:00https://b13rg.github.io/3COM-NIC-Review<p>3Com was a networking product manufacturer that sold networking gear such as switches, routers, access points, and network interface cards.
The company was founded in 1979, and was eventually bought by HP in 2010, where they continue to work on networking products.</p>
<p><img src="/images/3ComGigNic/the_box.jpg" alt="Da Box" width="500px" /></p>
<p>The 3C996B-T Network Interface Card (NIC) was put on the market in late 2001/early 2002.
The earliest product page for the card on 3Com’s website was dated November 18, 2001.
Even though it supports consumer type operating systems, the cards were meant to be installed in servers.
The packaging states that the card “offloads transfer cycle-intensive checksum processing from the host CPU to the NIC”.
It also supports Gigabit data transfer, which at the time was a fairly new and had just been established (1999).</p>
<p>The box declares the card to be a “Gigabit Fiber-SX Server Network Interface Card” and is labeled as a 3C996-SX, which is the fiber model of the NIC.
Inside was actually a 3C996B-T, which is the (much) cheaper ethernet model.</p>
<p><img src="/images/3ComGigNic/card_shot.jpg" alt="NIC(e) card" width="500px" /></p>
<p>When first released, the SX model sold for $695.00, while the ethernet model was only $169.
Today, the cards aren’t quite in demand as they once may have been.
I was able to find the card on ebay selling for ~$10 + shipping.
The internet archive has an archive of 3Com’s original product page for the cards which can be seen <a href="https://web.archive.org/web/20020917225824/http://www.3com.com/products/en_US/prodlist.jsp?tab=cat&pathtype=purchase&cat=19&selcat=Network+Interface+Cards&family=110">here</a>
When I bought it the box was still sealed in plastic wrap, which had a label with the correct model on it so I figure it was either mis-boxed or the card was reboxed and sealed.</p>
<p><img src="/images/3ComGigNic/box_contents.jpg" alt="Whatcha get" width="500px" /></p>
<p>Once opened, there are a few different things included.
There is the card of course, contained within some plastic packaging.
Additionally, there is the warranty, a quickstart guide, a CD-Rom with drivers and test utilities, and a “Remote Wake-Up” cable.
The “Remote Wake-up” cable is meant to be installed in a supported connector on the motherboard, which allows the computer to be remotely started through the network.</p>
<p>For managing all that gigabit traffic this card uses a Broadcom BCM 5701TKHB chip whose datasheet can be found <a href="https://pdf1.alldatasheet.com/datasheet-pdf/view/92603/BOARDCOM/BCM5701.html">here</a></p>
<p><img src="/images/3ComGigNic/chip_shot.jpg" alt="Mr. Chip" width="500px" /></p>
<p>Interestingly, the chip is branded with both the 3Com and Broadcom logos, with the text “Technology Alliance” underneath.
After a cursory internet search, I found an article from December of 2000 detailing how 3Com and Broadcom teamed up to work on <a href="https://www.edn.com/electronics-news/4342691/Broadcom-3Com-Unite-To-Deploy-Gigabit-Ethernet">deploying gigabit ethernet into business networks</a>.
The release of this card came along about a year later, so this card must be a result of that partnership and why both companies are on the chip.</p>
<hr />
<p>Included with the card is a CD-Rom with all the drivers needed to operate it.
The root of the disk is as follows:</p>
<p><img src="/images/3ComGigNic/cd_dir.JPG" alt="Da Box" width="500px" /></p>
<p>Testing utility tools were also included that allow the user to directly test the Broadcom chip on the card.
Though the SX and B-T models interface with different hardware, they both have very similar system requirements.
They were designed to be put in a PCI 2.2 or PCI-X 1.0 compliant server, and supported the following operating systems:</p>
<ul>
<li>Windows Microsoft XP</li>
<li>Windows 2000 (Server)</li>
<li>Windows NT (4.0)</li>
<li>Novell NetWare 4.2, 5.x, 6.x</li>
<li>Linux 2.2, 2.4</li>
<li>UnixWare 7.0</li>
<li>OpenServer 5.0</li>
<li>Sun Solaris x86</li>
</ul>
<p>Also included in the drivers disk is software to test the Broadcom chip.
It allows the user to poerform tests on the chip in two modes: manufacturing and engineering.
In manufacturing mode, it will run all tests defined in the config.
If it hits an error, it will display the error, and exit the testing program.
The engineering mode allows a user to interactivly run different tests.
Different commands can be entered to perform the different tests, whose results are printed to the screen.
Even though the card itself is targeted toward *nix and Windows Nt type operating systems, the testing utility is meant to be run on Dos 6.22.
The tests are split into 4 categories:</p>
<ul>
<li>Register Tests</li>
<li>Memory Tests</li>
<li>Miscellaneous Tests</li>
<li>Data Tests</li>
</ul>
<p>While in manufacturing mode, not all tests will be ran.
Some tests, like the hardware’s Build-In-Self-Test, are disabled by default because of “intermittent failure” or other issues.
Only 4 other tests are not run by default.
The config files for the tests are stored in a binary format so it is difficult to see what the defaults are without the documentation.</p>
<p>The software also provides a way to modify data stored in the card’s eeprom.
It allows an adminstrator modify things like MAC prefix, the asset tag, voltages, speeds and a few other settings.
In order to update the values, first you create <code class="language-plaintext highlighter-rouge">eeprom.txt</code> and specify each property in a <code class="language-plaintext highlighter-rouge"><keyword> = <argument></code> format.
The utility program is then uses this file and a supplied password to generate a <code class="language-plaintext highlighter-rouge">.bin</code> file of the changes, which can then be applied to the card.</p>
<hr />
<p>I still plan on testing the card in a real system once I am able to get one running.
I am interested to see how it performs compared to other, more modern computers with built in networking.
It would also be fun to dig into the testing utilities and see how well it performs after so many years.</p>
<p>If you would like a copy of the drivers included with the card, you can find a zipped up copy of it <a href="/files/3ComGigNic/3C996B_T_drivers.zip">here</a>.</p>Brendan ByersIcebergByers@protonmail.comThe 3C996B-T Network Interface Card (NIC) was put on the market in late 2001/early 2002. This article takes a look at the card and explores it's capabilities.The Life of MS-DOS2019-04-03T00:00:00+00:002019-04-03T00:00:00+00:00https://b13rg.github.io/Life-of-MS-DOS<p>First released on August 12, 1981, MS-DOS became the foundation for business computing for almost two decades.
MS-DOS stood for Microsoft Disk Operating System and was often referred to simply as “DOS”.
It is the software that helped build Microsoft, becoming the foundation Microsoft built the Windows operating system on.
It went through 8 (and a half-ish) major revisions, with the final version being shipped with Windows ME in September, 2000.
Before I talk about MS-DOS proper, I talk about it’s “grandparents” if you will, Digital Research’s CP/M and Seattle Computer Product’s 86-DOS.</p>
<p>In addition to writing this article, I also made the following cladogram chart showing the relationships of different DOS “flavors”.
I hope to use it in other articles to walk through the history of Digital Research’s DOS, DR DOS and the many transformations it went through.</p>
<p>The code for the chart can be found in my <code class="language-plaintext highlighter-rouge">Projects</code> repository, under the <a href="https://github.com/B13rg/Projects/tree/master/Dos%20Lineage%20Cladogram">Dos Lineage Cladogram</a> folder.</p>
<p><img src="/images/MSDOS/MSDOS_family_tree.png" alt="MS-DOS Family Tree" width="700px" /></p>
<p><a href="/images/MSDOS/MSDOS_family_tree.png">Link to full-size image</a></p>
<hr />
<h2 id="cpm">CP/M</h2>
<p>CP/M was a operating system designed by Gary Kildall for Digital Research.<br />
It was designed for 8-Bit computers, so it ran on Intel 8080/85 and Z80 processors.
CP/M originally stood for “Control Program/Monitor” and later “Control Program for Microcomputers”.
CP/M 1.4 was the first major version released, later followed by version 2.2.
CP/M was even able to run on the Commodore 64, though it required a specialized cartridge that housed a Z80 processor.
At the time, IBM was looking for an operating system to use with their IBM PC line of products.
IBM discussed licensing CP/M from Digital Research, but they were unable to come to an agreement.
IBM looked elsewhere for an operating system and in July of 1980 began talks with Microsoft about their development of MS-DOS, which was based on 86-DOS by Seattle Computer Products.</p>
<p>While IBM moved on, Digital Research went on to develop their own version of DOS based on CP/M 86 that eventually became DR DOS.
As ownership of Digital Research changed, later versions had different names like Novell DOS and Caldera DR-OpenDOS (what a mouthful).
This branch of the DOS family is still somewhat alive under the name DR-DOS (with the hyphen) with the last real update being back in 2011.
The website for the project is now seemingly dead but it can still be viewed on archive.org.
More about this project can be found <a href="https://web.archive.org/web/20160425031024/http://www.drdosprojects.de/index.cgi/download.htm">here</a>.</p>
<h2 id="qdos--86-dos">QDOS / 86-DOS</h2>
<p>86-DOS was originally developed by Seattle Computer Products (SCP) beginning in April of 1980.
It was originally named QDOS (Quick and Dirty Operating System), but was changed to 86-DOS once they began shipping in August of 1980.
It was first developed to be packaged with CPM’s 8086 computer kit.
SCP originally wanted to simply use Digital Research’s 8086 version of CP/M, but with an uncertain release date SCP made the decision to develop an OS themselves.
While writing it, the programmer Tim Paterson referenced the manual for CP/M-80 which explains why CP/M and QDOS were so alike.
Because of its similarity to CP/M, it was easy to port programs originally designed for CP/M on 8080 and Z80 processors to QDOS, which targeted 8086 processors.
Development of the software ended up taking only 6 weeks.</p>
<p>QDOS 0.11 was released in August of 1980, which is when it was renamed to 86-DOS.
Microsoft ended up licensing it from SCP in December of 1980 and in May of the following year hired Tim Patterson to assist in porting it to the IBM PC.
A month before Microsoft’s new operating system was release, they purchased all rights to 86-DOS from SCP for only $50,000.
After settling a lawsuit over the deal with SCP, Microsoft later ended up paying a total $1 million.
Microsoft took it’s adapted 86-DOS 1.14, created MS-DOS 1.10/1.14, and licensed it to IBM who sold by IBM under the name PC DOS 1.0.</p>
<h2 id="ms-dos-and-pc-dos">MS-DOS and PC DOS</h2>
<p>PC DOS versions 1.0, 1.1, 2.0, 2.1, 3.0, 3.1, 3.2, 5.0, and 6.0 were developed primarily by Microsoft, though IBM made additions of their own specific to their computers.
For some versions, Microsoft didn’t directly contribute to development but IBM based their changes on existing code.[2]
This was one of the few instances where Microsoft licensed MS-DOS to another company and had allowed the company to rebrand it.
A few other versions that were licensed and rebranded were SB-DOS, COMPAQ-DOS, NCR-DOS AND Z-DOS.
Eventually, it started enforcing the MS-DOS name for all OEM’s except IBM.</p>
<p>While the development of different MS-DOS versions was fairly standard, version 4.0 and 4.1 were interesting.
MS-DOS 4.0 was based on MS-DOS 2.0 and was developed in paralell with MS-DOS 3.0.
This version was designed as a multitasking version of DOS.
It was designed to allow specially written programs to run in the background while the user continued to interact in the foreground, similar to services in Windows.
While being developed, IBM and other OEM’s weren’t interested in it so Microsoft instead had a limited release in Europe.
Interestingly, the same developers who worked on this multitasking version moved on to work on what became OS/2, an operating system for IBM PC’s.</p>
<p>Though MS-DOS 4.1 was worked on and developed, it never really saw a wider release.
It was interesting as an operating system, but “Microsoft at the time was a 100% OEM shop – we didn’t sell operating systems, we sold operating systems to hardware vendors who sold operating systems with their hardware.”[3]
Instead, the next “real” version of MS-DOS released was 4.00 which distinguished itself with an extra “0” in the version number.
This was the version that was also rebranded as PC DOS 4.0 for IBM.</p>
<h2 id="the-final-years">The Final Years</h2>
<p>MS-DOS 6.3 was the last version that was released as a stand alone program.
The next version, MS-DOS 7.0 was released as part of Windows 95.
Both Windows 95 Revision 2 and the first release of Windows 98 were equipped with MS-DOS 7.1 running things behind the scenes.
These were the first major versions of MS-DOS that were completely separate from PC DOS, whose version 7.0 was developed by IBM alone.</p>
<p>The final version of MS-DOS was released as a part of Windows ME in September of 2000.
This was the last version of windows that used MS-DOS as a foundation.
Windows XP moved to the NT kernel, whose primary difference was moving away from a monolithic kernel to a hybrid kernel.
With MS-DOS, the kernel and operating system exists completely within the kernel space.
Windows NT uses a safer structure, where the kernel is split between the kernel space and the user space.</p>
<p><img src="/images/MSDOS/win9xKernel.gif" alt="Windows 9.x Kernel Design" /></p>
<p>A diagram of Windows 95 Kernel Structure</p>
<hr />
<h2 id="further-reading">Further reading</h2>
<p>A writeup by Tim Patterson looking at the design decisions of MS-DOS: <a href="http://www.patersontech.com/dos/byte%E2%80%93inside-look.aspx">http://www.patersontech.com/dos/byte%E2%80%93inside-look.aspx</a></p>
<p>Writing about an early pre-release version of PC DOS: <a href="https://thestarman.pcministry.com/DOS/ibm090/">https://thestarman.pcministry.com/DOS/ibm090/</a></p>
<p>The released source code of MS-DOS 1.25 and 2.0: <a href="https://github.com/microsoft/ms-dos">https://github.com/microsoft/ms-dos</a></p>
<p>A page describing the changes in each version of MS-DOS and PC DOS: <a href="https://web.archive.org/web/20181006120605/https://sites.google.com/site/pcdosretro/doshist">https://web.archive.org/web/20181006120605/https://sites.google.com/site/pcdosretro/doshist</a></p>
<p>An archive of an MSDN article about multitasking DOS: <a href="https://web.archive.org/web/20190118134253/https://blogs.msdn.microsoft.com/larryosterman/2004/03/22/did-you-know-that-os2-wasnt-microsofts-first-non-unix-multi-tasking-operating-system/">https://web.archive.org/web/20190118134253/https://blogs.msdn.microsoft.com/larryosterman/2004/03/22/did-you-know-that-os2-wasnt-microsofts-first-non-unix-multi-tasking-operating-system/</a></p>
<p>A history of the personal computer. Chapter 12 (Microsoft in the 1980s) and Appendix B (Versions of DOS) are especially interesting: <a href="http://www.retrocomputing.net/info/allan/">http://www.retrocomputing.net/info/allan/</a></p>
<p>A collection of old operating systems, including disk images of many different DOS versions: <a href="https://winworldpc.com/library/operating-systems#">https://winworldpc.com/library/operating-systems#</a></p>
<p>A history of MS-DOS written by Digital Research: <a href="http://www.digitalresearch.biz/HISZMSD.HTM">http://www.digitalresearch.biz/HISZMSD.HTM</a></p>
<p>A description of the different features of MS-DOS 8.0, the last official release: <a href="http://www.multiboot.ru/msdos8.htm">http://www.multiboot.ru/msdos8.htm</a></p>Brendan ByersIcebergByers@protonmail.comFirst released on August 12, 1981, MS-DOS became the foundation for business computing for almost two decades. This article details different versions and releases that all stemmed from Gary Kildall's QDOS.Notes on building and testing the QUIC protocol2019-02-28T00:00:00+00:002019-02-28T00:00:00+00:00https://b13rg.github.io/QUIC-setup-and-testing<p>This is the process I went through to setup and test QUIC protocol.
I did this as part of a project for my Networking 476 course at OSU.</p>
<p>QUIC is a transport protocol that runs on top of UDP.
Quoting it’s draft:
“QUIC is a multiplexed and secure general-purpose transport protocol that provides:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>* Stream multiplexing
* Stream and connection-level flow control
* Low-latency connection establishment
* Connection migration and resilience to NAT rebinding
* Authenticated and encrypted header and payload
</code></pre></div></div>
<p>It is designed to run at the application level instead of at the kernel level, making it easier to update and manage.
At the time of this post it is at draft 18, <a href="https://datatracker.ietf.org/doc/draft-ietf-quic-transport/18/">located here</a>.
Google has also done their own implementation which is currently in use in the Chrome web browser.
It has been in use since around 2013, but it is different enough from the IETF QUIC to be incompatible so it is usually referred to as GQUIC.</p>
<p>To test and play with QUIC, you will need to build it yourself.
A list of different implementations is located in the <a href="https://github.com/quicwg/base-drafts/wiki/Implementations">quicwg/base-drafts</a>
git repository.
From that list I chose to build and test one titled “QUINN”.</p>
<h2 id="quinn">QUINN</h2>
<p>Repository: <a href="https://github.com/djc/quinn">https://github.com/djc/quinn</a></p>
<p>I used code from commit <code class="language-plaintext highlighter-rouge">aa8c293</code>.
To build quinn, you will need to install rust version >= 1.32.
There are some changes to how rust handles const released in version 1.31, and updating to 1.32 fixed the issues I was having.
I performed my tests on the WSL running on windows 10.
Installing rustc from apt gave me only version 1.30, so to properly install is you need to uninstall cargo and rust from WSL, and use the command: <code class="language-plaintext highlighter-rouge">curl https://sh.rustup.rs -sSf | sh</code>.
Once that is complete and installed, you need to either restart the terminal or use the command <code class="language-plaintext highlighter-rouge">source $HOME/.cargo/bin</code> to add cargo and rustc to the PATH.
Once I had rust properly installed, I was able to build and run the client and server.
For recording performance metrics, it is important to build them in release mode.</p>
<h3 id="server">Server</h3>
<p>To build the server, use the command <code class="language-plaintext highlighter-rouge">cargo build --release --example server</code>.
This will build the server code and place it in <code class="language-plaintext highlighter-rouge">./target/release/examples/</code>.</p>
<p>When starting the server, it is important to pass in both the address to listen to (<code class="language-plaintext highlighter-rouge">--listen</code> flag) and the folder from which to serve files.
Here’s the command I used to run it: <code class="language-plaintext highlighter-rouge">./target/release/examples/server --listen 127.0.0.1:4433 ./</code>.
Within the current directory, I created a folder named <code class="language-plaintext highlighter-rouge">www</code>, which is where I placed the various test files I generated.<br />
Look at the test files section to see how I created them.</p>
<h3 id="client">Client</h3>
<p>Before building the client code, I made two modifications to the source.
My tests mostly focused on transfer speeds, so I generated random-filled files of different sizes.
The client is coded as to output the files it receives to STDOUT, which it does not like.
To stop the client from output text, you’ll just need to comment out two lines in <code class="language-plaintext highlighter-rouge">quinn/examples/client.rs</code>, 149 and 150.
When building you will get a warning about line 7, but is ok to ignore.</p>
<p>To build the client, I used <code class="language-plaintext highlighter-rouge">cargo build --release --example client</code>.
This will build the client code and place it in <code class="language-plaintext highlighter-rouge">./target/release/examples/</code>.</p>
<p>When running the client, you only need to supply the address to request.
Even though <code class="language-plaintext highlighter-rouge">127.0.0.1</code> was supplied to the server, when running the client is important to use <code class="language-plaintext highlighter-rouge">localhost</code>.
This is because the client will to a DNS lookup on the address, and it will fail with the plain ip octets.</p>
<p>To run the client, I called <code class="language-plaintext highlighter-rouge">target/release/examples/client https://localhost:4433/www/250mb.file</code>.
I had previously created a folder named <code class="language-plaintext highlighter-rouge">www</code> with a few test files in it.<br />
The path after the port number is based on the path given to the server when you start it.</p>
<p>The client will download the file, then give a summary consisting of when it connected, requested, and received a response.
Here is some example output:</p>
<pre><code class="language-()">root:quinn# ./target/release/examples/client https://localhost:4433/www/250mb.file
connected at 3.1152ms
request sent at 4.7796ms
response received in 18.3998206s - 13268.642 KiB/s
drained
</code></pre>
<hr />
<h2 id="test-tools">Test tools</h2>
<h3 id="wireshark">Wireshark</h3>
<p>https://www.wireshark.org/download.html</p>
<p>To capture packets, I used wireshark. In order to be able to capture quic packets, you will need to download version >= 3.0.0.
My copy of wireshark is at 3.0.0rc1 (v3.0.0rc1-0-g8ec01dea).</p>
<p>When capturing those packets, be sure to filter the traffic to quic only by typing in <code class="language-plaintext highlighter-rouge">quic</code> in the filter bar.
This is how I captured the pcaps.</p>
<h3 id="spindump">Spindump</h3>
<p>https://github.com/EricssonResearch/spindump</p>
<p>This is used to statically analyze quic packets and get more performance metrics from them.
To install</p>
<ol>
<li>First clone the repository: <code class="language-plaintext highlighter-rouge">git clone https://github.com/EricssonResearch/spindump</code>.</li>
<li>Install the necessary packages: <code class="language-plaintext highlighter-rouge">sudo apt install make gcc libpcap-dev libncurses5-dev</code></li>
<li><code class="language-plaintext highlighter-rouge">cd spindump</code></li>
<li>Build it: <code class="language-plaintext highlighter-rouge">make</code></li>
<li>Install it: <code class="language-plaintext highlighter-rouge">sudo make install</code></li>
</ol>
<p>Now spindump should be installed.
You can check if it is by running <code class="language-plaintext highlighter-rouge">spindump --version</code>.
This is what I got:</p>
<pre><code class="language-()">root:spindump# spindump --version
version 0.11 January 22, 2019
</code></pre>
<p>I wasn’t able to get spindump to listen on the lo interface, but I believe it is because of how the WSL netowkring is setup.
Instead, you are able to feed in PCAP-format files for it to analyze through the <code class="language-plaintext highlighter-rouge">--input-file</code> flag.
Just take the recordings from wireshark and feed them through to analyze your tests with this tool.</p>
<hr />
<h2 id="test-files">Test Files</h2>
<p>To test the protocol, it is useful to have files of different sizes to test speeds etc.
To create a 250MB file full of random data, I used <code class="language-plaintext highlighter-rouge">head -c 250MB /dev/urandom > 250mb.file</code>.
To create a 2MB file full of zeros, you can use <code class="language-plaintext highlighter-rouge">head -c 2MB /dev/zero > 250mb.file</code>.</p>
<p>Be sure to place these files somewhere in the path of the directory passed in when starting the server.</p>Brendan ByersIcebergByers@protonmail.comThis is the process I went through to setup and test QUIC protocol, which is a transport protocol that runs on top of UDP.Making a Webpage out of an XML file2018-08-01T00:00:00+00:002018-08-01T00:00:00+00:00https://b13rg.github.io/Xsl%20and%20Xml<p>XML is traditionally used to store and transport data in a way that is readable to both computers and people.
At my job as an engineering intern at <a href="https://www.opendental.com/">Open Dental</a>, we save our database schema as an XML file for each minor version we produce.
Between versions there will be new columns, new tables and other differences.
We post each version of the schema online as a plain XML file.
This post describes how I used an XSL file to implement an webpage with some simple QOL additions.</p>
<p>The result of this post can be found at: <a href="https://opendental.com/OpenDentalDocumentation18-2.xml">https://opendental.com/OpenDentalDocumentation18-2.xml</a></p>
<p>The method used to display the webpage is unusual to say the least.
Each version of documentation is stored as an XML file on the server.
When a web request is made, the XML file is served in addition to an XSL file, which controls how the XML file is displayed.
This is usually used to embed XML data in a webpage.
The XSL is a style sheet much like CSS, where is describes how an XML file should be displayed.</p>
<p><a href="https://www.w3.org/Style/XSL/WhatIsXSL.html">A good summary of XSL functionality is here</a></p>
<hr />
<p>Before I made the changes, it was much more difficult to find the information you needed from the page.
When the page was loaded, you were presented with a list of all the tables that extended far off the screen.
If you were trying to find a specific table, you would spend your first few seconds wildly spinning the scroll wheel as fast as it could go.</p>
<p><img src="/images/XmlWebpage/oldLayout1.PNG" alt="Scrolling Galore" /></p>
<p>Below the enormous list of tables was the descriptions of the tables themselves.
Each database table was constructed as a table, titled with the name of the table and the general description underneath.
Below that each column was listed, and the order, name, type and summary were listed.
If you wanted to find a specific table, you either had to find the table name in the list of tables, or scroll until you found it.
Looking up a table for reference took a long time and really gave the scroll wheel a workout.</p>
<p><img src="/images/XmlWebpage/oldLayout2.PNG" alt="Page Down is you friend" /></p>
<p>Once you found the table you were looking for if you wanted to compare it to a previous version, you had to navigate back, select the version, then scroll to the table in question.
To me this workflow was absolutely infuriating, so I set out to fix it.</p>
<hr />
<p>When I was designing the page I wanted to obviously make it much easier to use.
I decided to split the page into a navigation pane and a table pane, with the list of table names on the left and the tables themselves on the right.
I also wanted them to scroll independently so searching for a table name wouldn’t screw with what was displayed in the tables pane.</p>
<p><img src="/images/XmlWebpage/Initial_Design.jpg" alt="Initial Design" /></p>
<p>Additionally, I wanted to add a filter function to the navigation pane to make finding a specific table quicker.
Instead of needing to find the table you wanted in a block of text, I wanted the list of tables to change as the filter term was typed in.
So if a user filtered on the string “code”, only tables containing the term as a substring would be shown.
In our case, it would show table names like “proccodenote”,”codesystem” and “zipcode”.</p>
<p>A version selector was another function that I felt would be useful enabling a user to compare tables between versions much faster and easier.
Much of the time our techs will switch back and forth between versions to pick out new columns and their function.
Usually to do this one would have to go back a page, then select the correct version from the list.
Having a dropdown menu with all of the documentation versions listed makes it much easier to swap versions.</p>
<p>Finally, I wanted to add anchors to each of the tables.
This makes it possible to link to a specific table on the page, making it easier to share the table documentation with other engineers or customers.
Having the anchors would also make it less difficult to compare tables between versions because the page would immediately navigate to the table in question.</p>
<hr />
<p>The XSL stylesheet tells the web browser how to display the XML documentation file.
To make the website I used a combination of html and javascript.
Writing the html portion was relatively straightforward.
Each HTML tag is an element, and behaves much the same way regular HTML does.
XSL adds additional tags to use, allowing us to pull elements and attributes from the XML document in addition to looping and branching.
The XSL presented an interesting challenge because of how each page would need to be stateless.
When users navigate to the documentation, they navigate to the XML files.
It meant that I needed to design the XSL in such a way to be able to communicate across pages without depending on a server backend.
When the page is requested the user is simply served the XML and XSL files, nothing else.
This made it fun and interesting for me to figure out how to make the different functions work.</p>
<p>The navigation pane is filled (from the top) with a company image, the version drop down, the table filter, and the list of tables for that version.
The values in the dropdown menu are hardcoded, which sadly means a new entry needs to be added to list of options for each version release.
The option selected depends on the the XML being viewed, reading directly from the pathname in the URL.
It relies on the javascript portion to do the calculations.
Javascript is also used to perform the filtering.
The list of table names is defined in the XSL by looping through each table element in the XML file and recording the title.
Since the names of the table are distinct, I also use the table names as an anchor.
It also provides a human-readable method of referring to the tables.
It makes it easy to tell from a glance which table is being linked just by looking at the URL.</p>
<p>Beside the navigation pane is the tables pane.
It was relatively straight forward to construct in the XSL file.
I only needed to loop through each of the tables and pull the fields to display.
Each table is displayed using an HTML table, so it is very simply to make the header and just loop through the column elements.
Of course this introduces lots of nested looping, but we only touch each element once when constructing the tables luckily.</p>
<p>The javascript is what I am most proud of for this project.
Usually CSL are only meant to contain basic HTML formatting, but I was able to encapsulate the javascript in a CDATA tag.
This prevented javascript from being parsed as XML, which would of course throw errors.
From there is was easy to use some basic javascript to liven up the page and accomplish the design goals I set for myself.
When the documentation page is first loaded, it will parse the URL to determine which version is being shown, what anchor is currently set and the search term if there was one.
That way when popping between versions the only thing that would change would be the data.
When a new version was chosen a function would package the current page settings and build the destination URL out of them.
The chosen filter string and anchor would then persist between pages which I think is real slick.</p>
<p>Filtering was accomplished by refreshing the list of table names on each key up in the filter box.
To filter, we would loop through each table name and make a case-insensitive check to see if the filter string was present.
When we wanted to omit a table we simply set it’s display style to none.
Because the page is extremely lightweight, the filtering also feels crisp.</p>
<hr />
<p>In the end, I was very happy with the finished product (my boss was too haha).
It is now much easier and quicker to reference tables and schemas from the documentation.
In the future we may upgrade again to a more traditional and fully featured web page, but I am happy with what I was able to accomplish using just an XSL file.
If there is a need or want for it, it would be nice to add a few more features to the page, such as viewing multiple versions at once and auto-sensing the versions to display in the drop down.
I think both of these functions would probably need something driving the pages behind because of what it takes to access a version.
It would take some more work figuring out how to make synchronous requests from the XSL, but it sounds like a fun challenge.
Maybe someday!</p>Brendan ByersIcebergByers@protonmail.comXML is traditionally used to store and transport data in a way that is readable to both computers and people. This post describes how I used an XSL file to implement an webpage with some simple QOL additions.Atari 2600 “Basic Programming” Game2017-01-18T00:00:00+00:002017-01-18T00:00:00+00:00https://b13rg.github.io/atari-2600-basic-programming-game<p>An interesting game of the Atari 2600 era was “Basic programming”, written by Warren Robinett.
This game was released in 1979, and was touted to allow the player to talk to their computer, and program a variety of things.
Though it may seem like it would allow players to write in BASIC code, it instead used its own limited instruction set.</p>
<p><img src="/images/AtariBasicProgramming/Atari_Basic_Programming_Leaflet.jpg" alt="Ad from Atari Game Catalog" /></p>
<p>It was also one of the few games that actually used the Atari keypad.
It came with inserts that you’d put in the controllers to type out text and navigate the screen.
It utilized both keypads, having the player slide them together using a tongue and groove system.
From here the player can begin programming.</p>
<p><img src="/images/AtariBasicProgramming/Basic_Programming_Inserts.jpg" alt="Controller Inserts" /></p>
<p>The game gave you five regions that showed different parts of your program.
The “Program” region is where instructions were inputted.
The “Stack” region gave you temporary results as the computer was running it.
Next the “Output” region showed the output of the written code.
The “status region showed the amount of memory available, and the speed of execution.
Finally, the “Graphics” region showed two colored squares that could be manipulated under program control.
By switching the difficulty switches, you could hide the titles of the regions and show the display region.</p>
<p><img src="/images/AtariBasicProgramming/Basic_Programming_Screen.png" alt="Game Screen with 5 regions" /></p>
<p>Sadly, the game only allowed 9 lines of code, severely restricting the complexity of programs that could be made. By removing the “Status”, “Program” and “Stack” regions a player could add another two lines of code.
Being so limited, the instruction booklet outlined just about all the programs you could write.
For example, the game Pong could be programmed using the following instructions:</p>
<pre><code class="language-basic">Hor 2 ← Hor 2+Key
If Ver 1>90 Then Ver 1 ← 88
If Hit Then Ver 1 ← 9
Ver 1 ← Ver 1+If Ver 1 Mod 2 Then 8 Else 92
Hor 1 ← Hor 1+7
Goto 1
</code></pre>
<p>One of the most difficult parts of the programming process was cycling through to the correct character.
Overall, it was a good introductory to programming, but by no means a masterpiece of game design.
Though it can be easily overshadowed by anything today, it is still interesting to see an extremely basic programming game run on the constrictive hardware of the 2600.</p>
<p>The transcribed manual for the game can be found at <a href="https://atariage.com/manual_html_page.html?SoftwareLabelID=15">https://atariage.com/manual_html_page.html?SoftwareLabelID=15</a></p>Brendan ByersIcebergByers@protonmail.comAn interesting game of the Atari 2600 era was “Basic programming”, written by Warren Robinett. This game was released in 1979, and was touted to allow the player to talk to their computer, and program a variety of things.