<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>8bitworkshop Blog</title>
    <link>https://8bitworkshop.com/blog/feed.xml</link>
    <description>The online IDE for 8-bit retro developers.</description>
    <atom:link href="https://8bitworkshop.com/blog/feed.xml" rel="self"/>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Sun, 05 Jul 2020 18:31:59 +0000</lastBuildDate>
    <item>
      <title>The Mango One</title>
      <link>https://8bitworkshop.com/blog/verilog/the-mango-one-6502-computer.md.html</link>
      <description>In 1976, the first 6502-based hobbyist computers were just starting to appear. MOS Technology's own KIM-1 had a numeric pad and seven-segment display. The competing SYM-1 could draw simple characters on an oscilloscope. But the real breakthrough would come when the computer could receive input from a full keyboard, and output to a television set. Steve Wozniak demonstrated such a device at Homebrew Computer Club, a 6502-based machine that could drive a 40 column by 24 row character display, and could run Woz's own Integer BASIC. This device would later be sold as the Apple I. We're going to create a similar device in the 8bitworkshop IDE using Verilog. For the 6502 CPU, we'll use an [open-source model](https://github.com/Arlet/verilog-6502) created by Arlet Ottens. To make it work with the Verilator simulator used by the 8bitworkshop IDE, we have to turn off a few warnings: These make the Verilog compiler ignore things like incomplete or overlapping case statements, and signals that are used both synchronously and asynchronously. It's not a big deal, it'll still simulate correctly. In our main module, we hook up this `cpu6502` module to various wires: The real 6502 has a tristate data bus -- it uses the same wires for input and output. This module has separate buses for in and out. Whenever the CPU needs to read a byte, it'll put the address on `AB` and read from the `DI` input on the following cycle. When it needs to write, it'll raise the `WE` signal and write the byte to the `DO` output. We don't use interrupts in this demo, nor do we ever have to pause the CPU. So we set the `IRQ`, `NMI`, and `RDY` signals to constant values. This is equivalent to pulling the signal up (1) or down (0) with a resistor. The Mango One's memory map is very similar to the Apple I: Start | End      | Description In our main module, we handle reads and writes from/to the CPU via `casez` statements. This allows us to easily respond to address ranges. For example, this is how the CPU reads from RAM and ROM: Writing to RAM is similar, and occurs in a separate **always** block. When the write-enable flag (`WE`) is enabled, we copy the value from the CPU's data output bus (`DO`) into RAM: The 6821 PIA is a common feature in 6502 designs, and connects the CPU to the outside world. Even the Commodore 64 had a couple of them. In the Apple I, it's configured to read from the keyboard (input) and drive the terminal (output). We're not going to simulate the 6821 entirely, just the functions we need: Address | Function When a key is pressed in the IDE, the module can receive the ASCII value via the `keycode` signal. If the high bit is set, a key has been pressed, and the module acknowledges it via the `keystrobe` signal: The CPU can read $D011 at any time to see if a key has been pressed: The Apple II uses a similar scheme to read the keyboard. It's very convenient to have the hardware return the ASCII value -- even later computers like the C64 and MSX require that the CPU scan the keyboard row-by-row and use a lookup table. Woz's design didn't involve a RAM-based frame buffer, but used several Signetics chips to implement a circular buffer. The display logic would circulate the bits in the buffer while rendering to CRT, and allow the CPU to insert single characters when idle. We'll emulate this concept in our `signetics_term` module. Here's how we wire it up: The terminal raises the `tready` signal whenever it is available for writes. The CPU can read this flag in the high bit of address $D012: We raise the `te` signal when we want to feed a character to the terminal, which it reads from the CPU data output bus. This signal will only be raised when we are writing to address $D012. The `dot` wire is the output video signal from the terminal. It uses the sync generator's horizontal and vertical position to look up pixels in a character ROM. Woz wrote a 256-byte *monitor program*, commonly referred to as *WozMon*. It's a simple utility which allows the operator to inspect RAM, modify RAM, and execute code in RAM or ROM. We've written our own version called *MangoMon*. In our **initial** block, we use the `$readmemh` command to read the ROM data from virtual files in the IDE. Verilog expects this data in textual format, one hexadecimal byte (or word) per line. The file `mangomon.hex` contains our custom monitor program and CPU vectors. Here are the commands: Command   | Function Enter           | Dump next 8 bytes How does our optimized code compare to his? Well, we saved maybe 8 bytes over his version, but we didn't initialize the PIA chip (our design doesn't simulate PIA configuration) and we don't allow an ending address for memory dumps. Woz is still the king of optimization! We've learned that we can simulate a 6502-based computer in your browser with Verilog and 8bitworkshop! You can check out the source code in [GitHub](https://github.com/sehugg/mango_one), or you can [play around with it in 8bitworkshop](http://8bitworkshop.com/redir.html?platform=verilog&amp;githubURL=https%3A%2F%2Fgithub.com%2Fsehugg%2Fmango_one&amp;file=mango1.v). Also check out our book "[Designing Video Game Hardware in Verilog](https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?tag=pzp-20)" where we design an entire game system using a custom 16-bit CPU.</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/verilog/the-mango-one-6502-computer.md.html</guid>
    </item>
    <item>
      <title>3.5.0 Release - The Island of Misfit Platforms</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-5-0.md.html</link>
      <description>8bitworkshop now supports *five* additional 8-bit platforms! They don't really *fit* in with any of our books, though they use the same toolchains as the other 6502 and Z80 platforms. Thus, you can program all of them in either C or assembler! We'll do some follow-up posts in the near future describing technical and programming details for each platform. For now, we'll give a quick overview, starting with a very important video chip. The TMS9918 chip design started in 1977, the same year the Atari 2600 was released to the world. It was the first consumer chip to interface directly to DRAM. But since memory was so expensive back then, it wouldn't see full adoption until the early 80s. The TI 99/4A was released in 1981 with a TMS9918A driving a full 16 KB of video RAM. The main CPU could only address 256 bytes of scratchpad RAM directly, but could dip into the VDP's RAM when needed. No matter, the VDP stole the show. It could display a character-mapped or bitmapped background with 15 different colors. It was the first system to coin the term "sprites", and could smoothly move 32 of them across the screen. The next three platforms all use a variant of the TMS9918 chip for video display, paired with a Z80 CPU. Their architectures are all close enough that we can use the same C library for these platforms. This library doesn't depend on a specific BIOS, but you can copy bitmap fonts from ROM to RAM if they're available. The  gave Atari a run for their money in 1982 by bundling a near-perfect port of *Donkey Kong* with the console. It included a full 16 KB of video memory, but also 8 KB of main RAM that could power complex games and even a Logo programming package. No one really agrees on what  stands for, but it was an early 80s home computer standard promoted by Microsoft and Japanese manufacturers. These machines featured similar hardware to a ColecoVision albeit with more RAM, and a full keyboard and expansion slots. The platform enjoyed success in Japan, South Korea, Brazil, and other countries. The 8bitworkshop IDE includes the open-source [C-BIOS](http://cbios.sourceforge.net/). It doesn't include a BASIC interpreter, but supports most of the simple BIOS functions, like console I/O. Sega's SG-1000 console was almost hardware-identical to the ColecoVision, but its successor, the was a significant upgrade, with more color depth and hardware scrolling. Yet it remained backward-compatible with the TMS9918A to play older titles The was announced and made available via mail-order in 1977, the same year the TMS9918A's design was conceived. It was originally announced as the "Bally Home Library Computer" and then as the "Bally Professional Arcade". The Astrocade packed in 8 KB of RAM, available at a volume discount due to its failure to pass specification tests, but good enough to be used as video RAM. It included a video display chip developed by Dave Nutting Associates for Midway, the same chip used in standup arcade games like Gorf and Wizard of Wor. This chip did not include hardware sprites, but instead could accelerate video RAM operations via a function generator. It could be configured to shift, expand, combine, mirror, and rotate bytes as they're written to the frame buffer. The ambitious system never attained the popularity of the Atari 2600. It had odd controllers and overheating problems. The Astrocade's built-in BIOS provided a ton of features that the tiny game ROMs could use -- a menuing system, object display and movement, music, BCD math, and more. We've actually written a compatible open-source BIOS, called AstroLibre, which we use in the IDE. The Atari 7800 was the first console from Atari designed by an outside company, General Computer Corporation (GCC), who had parlayed their lawsuits from game manufacturers into gainful employment. It was supposed to have been released in 1984, but internal Atari drama postponed its release until 1986. It was backwards-compatible with the Atari 2600, but since it was nine years old by this time, this wasn't as much of a selling point. While the Atari 2600 requires cycle-exact programming to even draw a simple sprite, the Atari 7800's graphics allow a more hands-off approach. Its MARIA chip operates exclusively via DMA, reading from RAM at high speed and drawing into an internal frame buffer. Each scanline is defined as part of a Display List, and the entire screen is defined by a collection of these -- a Display List List (really!) Unlike the ANTIC chip designed by Jay Miner and Joe Decuir, MARIA required expensive static RAM. The new [8bitworkshop IDE 3.5.0 release](http://8bitworkshop.com/v3.5.0/) has lots of other new features: New Z80 Simulator Memory Probe and CRT Probe You might be asking, how do I program this stuff? The included code samples will give you a head start, and there are plenty of links to technical info on the [awesome-8bitgamedev](https://github.com/sehugg/awesome-8bitgamedev) list. Happy programming!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-5-0.md.html</guid>
    </item>
    <item>
      <title>3.4.0 Release: NES Support (and New Book!)</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-4-0.md.html</link>
      <description>We've added yet another platform to the 8bitworkshop IDE, the legendary You can program in both C and 6502 assembler, and there are a ton of examples to get you started. The IDE lets you write *C* using the *cc65* compiler toolchain. While it has lower performance and greater code size than a well-written assembly program, you can still write a pretty good game in C. We use a fork of [Shriu](https://shiru.untergrund.net/aboutme.shtml)'s [*NESLib*](https://github.com/sehugg/neslib) library to interface with NES hardware features, and *Famitone* to play music and sound. The IDE also contains a handful of 6502 examples. They demonstrate how to initialize and warm up the PPU, basic display, scrolling, and controller management, and advanced tricks like scanline cycle counting and X/Y split screen. We've also got a new book, **"Making Games for the NES"**! You'll learn all about programming the NES -- hardware, PPU video, sound and music, scrolling, color palettes, split-screen effects, and more. Follow along with the IDE, which has lots of examples in C using the NESLib library. There's also a few chapters about 6502 assembly programming on the NES. We'll cover the basics of nametables, sprites, and controllers, and some advanced topics like timing the PPU line-by-line. Chapter List We want to show off creations from homebrew authors. Click on a project to see the emulated ROM in action, and press the button to open the source code in 8bitworkshop. The new [8bitworkshop IDE 3.4.0 release](http://8bitworkshop.com/v3.4.0/) has lots of other new features: GitHub Integration Asset Editor Memory Map Profiler Gamepad Support HTTPS Support Verilog Updates Minor Features Fixed bugs No more `local/` paths Okay, that's it for now. Go write some NES games!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-4-0.md.html</guid>
    </item>
    <item>
      <title>Designing Hardware with Verilog</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-3-0.md.html</link>
      <description>Big news! You can use the 8bitworkshop IDE to [write Verilog code](http://8bitworkshop.com/redir.html?platform=verilog), and see it executed instantly in real-time on a simulated CRT. Most computers are fast enough to render a game at 60 Hz, which requires simulating Verilog at almost 5 million ticks per second. This is all done in JavaScript! For example, here's a simple clock divider module: The IDE instantly compiles this and starts simulating, showing the output signals on the scope: There are a bunch of Verilog examples, from simple binary counters and video test patterns to sprite generators and video games. Many of them are based on old discrete arcade game designs, like Pong and Tank. The book describes 8-bit and 16-bit CPUs, the latter of which  powers a virtual game console with hardware sprites. There's even a built-in assembler, which can be configured to generate code for any CPU you can design. Here's some example code for the FEMTO-8 CPU described in the book: There's also a new 8bitworkshop book! [Designing Video Game Hardware in Verilog](https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?tag=pzp-20)! That was the big news, now here's the estoric stuff about the 3.3.0 IDE release: This makes it compile a lot faster, at the expense of slightly less optimal code. It also breaks certain bits of code -- namely, the `bcd_add` function, and the vector game samples. You can use the "Revert File" menu item to reset these back to the original, and they should work. You can ctrl-click on the VCS monitor and it'll set a breakpoint whenever the raster beam passes that position. It's rad!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-3-0.md.html</guid>
    </item>
    <item>
      <title>3.2.1: batari BASIC; the Sidebar</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-2-1.md.html</link>
      <description>I came across Fred Quimby's [batari BASIC](http://bataribasic.com/) while developing the first version of 8bitworkshop, and was intrigued. This is a BASIC compiler that targets the 6502, and has specific support for Atari 2600 features. For example, you might define the playfield like this: You could then set the foreground and background colors: And animate the playfield, scrolling it downward each frame: This tool had its 1.0 release in 2007, and most people seem content to use the built-in Windows executables packaged with the distribution. There are lots of bugs; many compile errors just lead to assembly errors. It could use a major overhaul with a new parser and code generator. But there's really nothing else like it,  and many [complete games](http://atariage.com/forums/topic/230005-batari-basic-game-listing/) have been built with this system. Its support libraries make things like bank-switching and kernel-drawing almost transparent to the programmer. Now it's integrated in the 8bitworkshop IDE, so give it a shot! There are several presets at the bottom of the list; they run the gamut from Click the "?" icon to see the manual. The IDE now has three resizeable panes, the leftmost of which is a new sidebar. Just drag the leftmost gutter to the right to expose it. It shows the various source files, include files, code listings, and tools like the Disassembler and Memory Browser. You can also create new include files using the "Add Files to Project" menu items. This adds `#include` statements to your main file (the file selected in the top bar pulldown.) These will appear in your sidebar too. For C projects, you can create "linked" files, which add The IDE compiles these and links them to your main file, just like a Makefile would. I found myself wanting a lightweight Markdown editor to use in the browser, so I integrated the  parser. Switch to the Markdown platform to write documents and see a real-time preview. Maybe later, I'll add stuff like including external images.</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-2-1.md.html</guid>
    </item>
    <item>
      <title>3.2.0: Font tools, bankswitching, and cassette loading</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-2-0.md.html</link>
      <description>New features in 8bitworkshop 3.2.0: Shotrcut   | Function Ctrl+Alt+P |Pause	 Ctrl+Alt+R |Resume		 Ctrl+Alt+. |Reset	 Ctrl+Alt+S |Single Step	 Ctrl+Alt+V |Single Frame	 Ctrl+Alt+L |Run To Cursor	 Ctrl+Alt+O |Run Until Return	 Ctrl+Alt+B |Step Backwards Happy Coding!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-2-0.md.html</guid>
    </item>
    <item>
      <title>3.1.0: VCS Love, Instant Replay and Playable Links</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-1-0.md.html</link>
      <description>In 8bitworkshop 3.1.0, we've given the VCS platform plenty of love: There's also some cool new features: You can go back in time and debug something, for instance. You can also embed it a website or blog post using an iframe. that fits into 250 characters. BTW, if you still see "3.0.0" in your browser URL, clear your cache or [navigate directly to the new version](/redir.html). Happy Coding!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-1-0.md.html</guid>
    </item>
    <item>
      <title>Version 3.0.0 Released!</title>
      <link>https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-0-0.md.html</link>
      <description>Version 3.0.0 of the 8bitworkshop IDE is out! Under the hood, there are lots of changes: This means you can save many more projects locally. It supports multiple include and link files, which is something we'll be taking advantage of in future updates. Listing files can be found here, as well as the Memory Browser and Disassembler views. Note that your browser may have cached the link to the old version. If you still see "2.1.1" in your browser URL, clear your cache or [navigate directly to the new version](/redir.html).</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/release/8bitworkshop-ide-release-3-0-0.md.html</guid>
    </item>
    <item>
      <title>The Galaxian-DK Connection</title>
      <link>https://8bitworkshop.com/blog/misc/namco-nintendo-connection.md.html</link>
      <description>For my recent book, I've had to research the hardware of various arcade game systems. While researching *Galaxian* I stumbled upon a website describing how to hack the graphic ROMs in *Donkey Kong* to turn Mario into Pauline. Reading it, I noticed something curious -- *DK*'s graphics were suprisingly similar to *Galaxian*'s layout. Not only did the background tilemap have the same dimensions and colors, but the 16x16 sprites were laid out the exact same way in memory, each 4-byte record having the same contents in the same order: Offset|Value 0     | Horizontal Position 1     | Sprite Pattern 2     | Sprite Attribute 3     | Vertical Position There were minor differences, like which bits flipped the X and Y direction, but essentially the same. Poking around the MAME source, I discovered that *Donkey Kong*'s video hardware was more advanced than *Galaxian*'s. different technique that could support 128 sprites in a single frame (16 on a single scanline). Did *DK* need all 128 sprites? Not really. But *DK*'s predecessor was Nintendo's *Radar Scope*, which had dozens of enemies attacking the player in a pseudo-3D formation, sort of a flat version of *Gyruss*. The story goes: *Radar Scope* didn't sell well in the U.S., so Nintendo internally solicited ideas for a new game that could use the same hardware. An idea from young designer Shigeru Miyamoto was chosen, and *Donkey Kong* was born. The game was then programmed into 2000 unsold *Radar Scope* games in the U.S. warehouse (whose landlord, Mario, had been eagerly awaiting the next rent payment.) A 1989 court case later revealed that a consulting firm named Ikegami Tsushinki did the actual hardware design and software programming for *Donkey Kong*, with guidance from Miyamoto and longtime Nintendo designer Gunpei Yokoi. In fact, *DK*'s ROM contained a hidden message and a phone number for reverse-engineers to find in case they wanted to apply for a job with Ikegami Tsushinki: Ikegami Tsushinki is also thought to have worked on several other Nintendo titles, including the previously mentioned *Radar Scope* -- none of which were big hits in the U.S. except for *Popeye*. After a falling out with Nintendo, they went on to do *Zaxxon* and *Congo Bongo* for Sega. But back to *Galaxian* -- the hardware has similarities with Nintendo games, but what about the code? I used a Python script to scan various ROMs and look for similar byte sequences that look like code fragments. I was surprised by what I found. There are several code routines that are shared by both *Galaxian* and *Donkey Kong*. Most of the shared code I found deals with drawing text and the scoreboard. There's also a complex "task list" system that orchestrates all of the subroutines, inserting items into a list and then running them from jump tables. These routines are long enough that it'd be unlikely they were written independently. *Galaxian* predates *DK* by two years. just two months after *Galaxian*. I wanted to see which other games shared *Galaxian* code, so I scanned a large batch of MAME ROMs for code that lives at the RST addresses. (RST is a Z80 instruction that jumps to preselected offsets using only a single byte, so commonly-used routines often get put at these addresses.) I found identical code segments in not only *Galaxian* and *DK* and their various clones/bootlegs, but Komani titles like *Scramble, Pooyan and Amidar* (naturally, since they're a licensee) and Taito titles like *Wild Western* and *Frontline*. For example, this routine is at offset `0x0008` and switches between two routines depending on whether any coins have been inserted: This snippet appears in several other games attributed to Ikegami Tsushinki, including which was developed by Namco in 1979. *Cutie Q* was the third game of Namco's *Gee Bee* trilogy and was released a month after *Galaxian*. It also appears in Nihon Bussan's *Moon Alien*, which was a derivative of Wikipedia page). So what are the possibilities? 1. Ikegami Tsushinki developed *Galaxian* 2. Ikegami Tsushinki engineers also worked on *Galaxian* 3. Ikegami Tsushinki reverse-engineered *Galaxian* 4. Ikegami Tsushinki *is* Namco! 5. Something innocuous, like a Z80 sourcebook that was passed around and copied. There may be another clue, which involves a concept called whereby homophonous words are associated with a given series of letters, numbers or symbols. This is often used as a memorization technique, for example the number 1492 can be memorized as: "i (1) yo (4) ku (9) ni (2)" meaning: "Wow! I can see land!" In *Donkey Kong* and *Radar Scope*, the default high score is 7650. 765 stands for "na-mu-ko" or Namco.  Derivatives of this number can be found in dozens of Namco produced video games.  (After Namco merged with Bandai, the goroawase number became 876, "ba-na-mu".) but *DK* developers had more than a year to borrow this feature.) It's clear, however, that *Donkey Kong* was developed on top of *Radar Scope*'s code base. The developers chose to retain the code that involved drawing and updating the scoreboard and bonus lives, and a couple of utility functions, but little else. What is unclear is how *Radar Scope* and *Galaxian* are connected. When I told my sigother about my findings, she found a video of Crazy Kong running on Galaxian hardware, using sounds from Galaxian. Crazy Kong was a weird clone of Donkey Kong that Nintendo eventually licensed for sale in Japan due to increased demand. It has numerous subtle and not-so-subtle differences in sound, graphics, animation, and gameplay, and runs on several Z80 platforms, including Galaxian and Crazy Climber. But where did Crazy Kong come from? Nintendo licensed a company called Falcon/Zaccaria to release Donkey Kong outside of the U.S -- an "official bootleg" if you will. But why would a small publisher bother tweaking inconsequential aspects of a pretty solid game? Could Crazy Kong actually be a leaked prototype version of DK, developed on Galaxian hardware? http://wiki.donkeykonggenius.com/Donkey_Kong_Code http://www.gamasutra.com/view/feature/134790/the_secret_history_of_donkey_kong.php?print=1 http://groundkontrol.com/2013/05/behind-the-barrels-hacking-donkey-kong-part-1/ http://scholar.google.com/scholar_case?case=14413211357527714092&amp;q=564+F.+Supp.+937&amp;hl=en&amp;as_sdt=2,5 https://en.wikipedia.org/wiki/Talk%3ACrazy_Kong http://donkeykongforum.com/index.php?topic=646.0 http://arcadeclassics.net/80s-game-videos/galaxian/ http://thedoteaters.com/?bitstory=galaxian https://www.arcade-history.com/?page=detail&amp;id=901 http://shmuplations.com/galaga/ http://www.usgamer.net/articles/35-years-ago-nintendo-had-its-first-brush-with-video-game-disaster http://www.crunkgames.com/?p=87&amp;page=3 http://www.ostermayer.ch/video.html - radar scope h/w (use in book?) Toru Iwatani (Pac-Man) Koichi Tashiro (Galaxian programmer, 2005 Namco head mobile division) Shigekazu Ishimura (Galaxian h/w) Shigeru Yokoyama (Cutie Q, Galaga) Tetsu Ogawa (programmer, Galaga) Akira Takundai (bosconian?) Hurashi Nagumo (bosconian) 5f1600195e2356eb5e235623 DK 05E9  214B36    LD      HL,#364B        ; start of table data 05EC  87        ADD     A,A             ; double the parameter 05ED  F5        PUSH    AF              ; save AF to stack 05EE  E67F      AND     #7F             ; mask bits 05F0  5F        LD      E,A             ; copy to E 05F1  1600      LD      D,#00           ; D := 0 05F3  19        ADD     HL,DE           ; add to table to get pointer 05F4  5E        LD      E,(HL)          ; load E with first byte from table 05F5  23        INC     HL              ; next table entry 05F6  56        LD      D,(HL)          ; load D with 2nd byte from table 05F7  EB        EX      DE,HL           ; DE &lt;&gt; HL 05F8  5E        LD      E,(HL)          ; load E with 1st byte from dereferenced table 05F9  23        INC     HL              ; next table entry 05FA  56        LD      D,(HL)          ; load D with 2ndy byte from derefernced table 05FB  23        INC     HL              ; next table entry 05FC  01E0FF    LD      BC,#FFE0        ; load BC with offset to print characters across 05FF  EB        EX      DE,HL           ; DE &lt;&gt; HL.  HL now has screen destination, DE has table pointer 0600  1A        LD      A,(DE)          ; load A with table data 0601  FE3F      CP      #3F             ; end code reached? 0603  CA2600    JP      Z,#0026         ; yes, return to program.  This will effectively RET twice 0606  77        LD      (HL),A          ; draw letter to screen 0607  F1        POP     AF              ; restore AF from stack.  is there a carry? 0608  3002      JR      NC,#060C        ; no, skip next step 060A  3610      LD      (HL),#10        ; yes, write a blank space to the screen 060C  F5        PUSH    AF              ; save AF 060D  13        INC     DE              ; next table data 060E  09        ADD     HL,BC           ; add screen offset for next column 060F  18EF      JR      #0600           ; loop again GALAXIAN 5282  22F1                      ; --- START PROC L22F1 --- 5283  22F1  21 5C 23    L22F1:  ld      hl,235Ch 5284  22F4  87                  add     a,a 5285  22F5  F5                  push    af 5286  22F6  E6 3F               and     3Fh             ; '?' 5287  22F8  5F                  ld      e,a 5288  22F9  16 00               ld      d,00h 5289  22FB  19                  add     hl,de 5290  22FC  5E                  ld      e,(hl) 5291  22FD  23                  inc     hl 5292  22FE  56                  ld      d,(hl) 5293  22FF  EB                  ex      de,hl 5294  2300  5E                  ld      e,(hl) 5295  2301  23                  inc     hl 5296  2302  56                  ld      d,(hl) 5297  2303  23                  inc     hl 5298  2304  EB                  ex      de,hl 5299  2305  01 E0 FF            ld      bc,0FFE0h 5300  2308  F1                  pop     af 5301  2309  38 0E               jr      c,L2319 5302  230B  FA 23 23            jp      m,L2323 5303  230E  1A          L230E:  ld      a,(de) 5304  230F  D6 30               sub     30h             ; '0' 5305  2311  FE 0F               cp      0Fh 5306  2313  C8                  ret     z 5307  2314  77                  ld      (hl),a 5308  2315  13                  inc     de 5309  2316  09                  add     hl,bc 5310  2317  18 F5               jr      L230E ffcb6028143e1077197719773a DK 031D  3A0D60    LD      A,(#600D)       ; Load A with player # (0 for player 1, 1 for player 2) 0320  CD4703    CALL    #0347           ; Loads HL with location for score (either player 1 or 2) 0323  11E0FF    LD      DE,#FFE0        ; load DE with offset for each column 0326  CB60      BIT     4,B             ; test bit 4 of timer.  Is it zero ? 0328  2814      JR      Z,#033E         ; yes, skip ahead 032A  3E10      LD      A,#10           ; A := #10 = blank character 032C  77        LD      (HL),A          ; clear the text "1" from "1UP" or "2" from "2UP" 032D  19        ADD     HL,DE           ; add offset for next column 032E  77        LD      (HL),A          ; clear the text "U" from "1UP" 032F  19        ADD     HL,DE           ; next column 0330  77        LD      (HL),A          ; clear the text "P" from "1UP" 0331  3A0F60    LD      A,(#600F)       ; load A with # of players in game 0334  A7        AND     A               ; is this a 1 player game? 0335  C8        RET     Z               ; yes, return 0336  3A0D60    LD      A,(#600D)       ; Load current player # 0339  EE01      XOR     #01             ; change player from 1 to 2 or from 2 to 1 033B  CD4703    CALL    #0347           ; Loads HL with location for score (either player 1 or 2) 033E  3C        INC     A               ; increase A, now it has the number of the player 033F  77        LD      (HL),A          ; draw player number on screen 0340  19        ADD     HL,DE           ; next column 0341  3625      LD      (HL),#25        ; draw "U" on screen 0343  19        ADD     HL,DE           ; next column 0344  3620      LD      (HL),#20        ; draw "P" on screen 0346  C9        RET                     ; return GALAX 4889  20AC  3A 0D 40    L20AC:  ld      a,(400Dh) 4890  20AF  CD 4E 21            call    L214E 4891  20B2  11 E0 FF            ld      de,0FFE0h 4892  20B5  CB 60               bit     4,b 4893  20B7  28 14               jr      z,L20CD 4894  20B9  3E 10               ld      a,10h 4895  20BB  77                  ld      (hl),a 4896  20BC  19                  add     hl,de 4897  20BD  77                  ld      (hl),a 4898  20BE  19                  add     hl,de 4899  20BF  77                  ld      (hl),a 4900  20C0  3A 0E 40            ld      a,(400Eh) 4901  20C3  A7                  and     a 4902  20C4  C8                  ret     z 4903  20C5  3A 0D 40            ld      a,(400Dh) 4904  20C8  EE 01               xor     01h 4905  20CA  CD 4E 21            call    L214E 4906  20CD  3C          L20CD:  inc     a 4907  20CE  77                  ld      (hl),a 4908  20CF  19                  add     hl,de 4909  20D0  36 25               ld      (hl),25h        ; '%' 4910  20D2  19                  add     hl,de 4911  20D3  36 20               ld      (hl),20h        ; ' ' 4912  20D5  CB 60               bit     4,b 4913  20D7  C0                  ret     nz 4914  20D8  3A 06 40            ld      a,(4006h) 4915  20DB  A7                  and     a 4916  20DC  C0                  ret     nz 4917  20DD  32 AB 40            ld      (40ABh),a 4918  20E0  C9                  ret 09a706031a8e2712132310f8 DK 0521  79        LD      A,C             ; load score 0522  81        ADD     A,C             ; double 0523  81        ADD     A,C             ; triple 0524  4F        LD      C,A             ; C is now 3 times A for use in the scoring table 0525  212935    LD      HL,#3529        ; #3529 holds table data for scoring 0528  0600      LD      B,#00           ; B := 0 052A  09        ADD     HL,BC           ; add offset for scoring table 052B  A7        AND     A               ; clear carry flag 052C  0603      LD      B,#03           ; for B = 1 to 3 052E  1A        LD      A,(DE)          ; load A with current score 052F  8E        ADC     A,(HL)          ; add the amount the player just scored 0530  27        DAA                     ; decimal adjust 0531  12        LD      (DE),A          ; store result in score 0532  13        INC     DE              ; next byte of score 0533  23        INC     HL              ; next byte of score to add 0534  10F8      DJNZ    #052E           ; Next B 0536  D5        PUSH    DE              ; save DE 0537  1B        DEC     DE              ; DE is now the last byte of score GALAX 5065  21AB  79                  ld      a,c 5066  21AC  81                  add     a,c 5067  21AD  81                  add     a,c 5068  21AE  4F                  ld      c,a 5069  21AF  06 00               ld      b,00h 5070  21B1  21 D0 22            ld      hl,22D0h 5071  21B4  09                  add     hl,bc 5072  21B5  A7                  and     a 5073  21B6  06 03               ld      b,03h 5074  21B8  1A          L21B8:  ld      a,(de) 5075  21B9  8E                  adc     a,(hl) 5076  21BA  27                  daa 5077  21BB  12                  ld      (de),a 5078  21BC  13                  inc     de 5079  21BD  23                  inc     hl 5080  21BE  10 F8               djnz    L21B8 5081  21C0  1B                  dec     de 5082  21C1  D5                  push    de 5083  21C2  1B                  dec     de 36ff2c7dfec030023ec032 DK 02E3  E61F      AND     #1F             ; mask bits.  A now between 0 and #1F 02E5  5F        LD      E,A             ; copy to E 02E6  1600      LD      D,#00           ; D := 0 02E8  36FF      LD      (HL),#FF        ; overwrite the task with empty entry 02EA  2C        INC     L               ; next HL 02EB  4E        LD      C,(HL)          ; load C with the 2nd byte of the task (parameter) 02EC  36FF      LD      (HL),#FF        ; overwrite the task with empty entry 02EE  2C        INC     L               ; next HL 02EF  7D        LD      A,L             ; load A with low byte of the address 02F0  FEC0      CP      #C0             ; &lt; #C0 ? 02F2  3002      JR      NC,#02F6        ; no, skip next step 02F4  3EC0      LD      A,#C0           ; reset low byte to #C0 02F6  32B160    LD      (#60B1),A       ; store into the task pointer 02F9  79        LD      A,C             ; load A with the 2nd byte of the task 02FA  21BD02    LD      HL,#02BD        ; load HL with return address 02FD  E5        PUSH    HL              ; push to stack so RET will go to #02BD = task list 02FE  210703    LD      HL,#0307        ; load HL with data from table below 0301  19        ADD     HL,DE           ; add the offset based on byte 1 of the task 0302  5E        LD      E,(HL)          ; load E with the low byte from the table below 0303  23        INC     HL              ; next HL 0304  56        LD      D,(HL)          ; load D with the high byte from the table 0305  EB        EX      DE,HL           ; DE &lt;&gt; HL 0306  E9        JP      (HL)            ; jump to address from the table GALAX 4800  2019  E6 0F       L2019:  and     0Fh 4801  201B  4F                  ld      c,a 4802  201C  06 00               ld      b,00h 4803  201E  36 FF               ld      (hl),0FFh 4804  2020  2C                  inc     l 4805  2021  5E                  ld      e,(hl) 4806  2022  36 FF               ld      (hl),0FFh 4807  2024  2C                  inc     l 4808  2025  7D                  ld      a,l 4809  2026  FE C0               cp      0C0h 4810  2028  30 02               jr      nc,L202C 4811  202A  3E C0               ld      a,0C0h 4812  202C  32 A1 40    L202C:  ld      (40A1h),a 4813  202F  7B                  ld      a,e 4814  2030  21 3D 20            ld      hl,203Dh 4815  2033  09                  add     hl,bc 4816  2034  5E                  ld      e,(hl) 4817  2035  23                  inc     hl 4818  2036  56                  ld      d,(hl) 4819  2037  21 0A 20            ld      hl,200Ah 4820  203A  E5                  push    hl 4821  203B  EB                  ex      de,hl 4822  203C  E9                  jp      (hl) DK 2c7dfec030023ec032 309F  E5        PUSH    HL              ; save HL 30A0  21C060    LD      HL,#60C0        ; load HL with start of task list [why?  L is set later, only H needs to be loaded here] 30A3  3AB060    LD      A,(#60B0)       ; load A with task pointer 30A6  6F        LD      L,A             ; HL now has task pointer full address 30A7  CB7E      BIT     7,(HL)          ; test high bit 7 of the task at this address.  zero? 30A9  CABB30    JP      Z,#30BB         ; yes, skip ahead, restore HL and return. [when would this happen??? if task list is full???] 30AC  72        LD      (HL),D          ; else store task number into task list 30AD  2C        INC     L               ; next HL 30AE  73        LD      (HL),E          ; store task parameter 30AF  2C        INC     L               ; next HL 30B0  7D        LD      A,L             ; load A with low byte of task pointer 30B1  FEC0      CP      #C0             ; is A &gt; #C0 ? (did the task list roll over?) 30B3  D2B830    JP      NC,#30B8        ; no, skip next instruction 30B6  3EC0      LD      A,#C0           ; yes, reset A to #C0 for start of task list 30B8  32B060    LD      (#60B0),A       ; store A into task list pointer 30BB  E1        POP     HL              ; restore HL 30BC  C9        RET                     ; return to program GALAX 1318  08F2                      ; --- START PROC L08F2 --- 1319  08F2  E5          L08F2:  push    hl 1320  08F3  26 40               ld      h,40h           ; '@' 1321  08F5  3A A0 40            ld      a,(40A0h) 1322  08F8  6F                  ld      l,a 1323  08F9  CB 7E               bit     7,(hl) 1324  08FB  28 0E               jr      z,L090B 1325  08FD  72                  ld      (hl),d 1326  08FE  2C                  inc     l 1327  08FF  73                  ld      (hl),e 1328  0900  2C                  inc     l 1329  0901  7D                  ld      a,l 1330  0902  FE C0               cp      0C0h 1331  0904  30 02               jr      nc,L0908 1332  0906  3E C0               ld      a,0C0h 1333  0908  32 A0 40    L0908:  ld      (40A0h),a 1334  090B  E1          L090B:  pop     hl 1335  090C  C9                  ret DK 059B  FE03      CP      #03             ; task parameter &lt; 3 ? 059D  D2BD05    JP      NC,#05BD        ; yes, skip ahead [when would it do this???  A always 0 or 1 ???] 05A0  F5        PUSH    AF              ; save AF 05A1  21B260    LD      HL,#60B2        ; load HL with player 1 score 05A4  A7        AND     A               ; parameter == 0 ? 05A5  CAAB05    JP      Z,#05AB         ; yes, skip next step 05A8  21B560    LD      HL,#60B5        ; else load HL with player 2 score 05AB  FE02      CP      #02             ; parameter == 2 ? [when would it do this ??? A always 0 or 1 ??? ] 05AD  C2B305    JP      NZ,#05B3        ; no, skip next step 05B0  21B860    LD      HL,#60B8        ; load HL with high score 05B3  AF        XOR     A               ; A := 0 05B4  77        LD      (HL),A          ; clear score 05B5  23        INC     HL              ; next score memory 05B6  77        LD      (HL),A          ; clear score 05B7  23        INC     HL              ; next score memory 05B8  77        LD      (HL),A          ; clear score 05B9  F1        POP     AF              ; restore AF 05BA  C3C605    JP      #05C6           ; jump ahead to task 2 05BD  3D        DEC     A               ; decrease A 05BE  F5        PUSH    AF              ; save AF 05BF  CD9B05    CALL    #059B           ; ???  call myself ??? 05C2  F1        POP     AF              ; restore AF 05C3  C8        RET     Z               ; return if Zero 05C4  18F7      JR      #05BD           ; else loop again GALAX 5123  21FE                      ; --- START PROC L21FE --- 5124  21FE  FE 03       L21FE:  cp      03h 5125  2200  30 26               jr      nc,L2228 5126  2202  F5                  push    af 5127  2203  21 A2 40            ld      hl,40A2h 5128  2206  11 AD 40            ld      de,40ADh 5129  2209  A7                  and     a 5130  220A  28 0E               jr      z,L221A 5131  220C  21 A5 40            ld      hl,40A5h 5132  220F  11 AE 40            ld      de,40AEh 5133  2212  3D                  dec     a 5134  2213  28 05               jr      z,L221A 5135  2215  21 A8 40            ld      hl,40A8h 5136  2218  5D                  ld      e,l 5137  2219  54                  ld      d,h 5138  221A  36 00       L221A:  ld      (hl),00h 5139  221C  23                  inc     hl 5140  221D  36 00               ld      (hl),00h 5141  221F  23                  inc     hl 5142  2220  36 00               ld      (hl),00h 5143  2222  EB                  ex      de,hl 5144  2223  36 00               ld      (hl),00h 5145  2225  F1                  pop     af 5146  2226  18 09               jr      L2231 5147  2228 5148  2228  3D          L2228:  dec     a 5149  2229  F5                  push    af 5150  222A  CD FE 21            call    L21FE 5151  222D  F1                  pop     af 5152  222E  C8                  ret     z 5153  222F  18 F7               jr      L2228 DK 05C6  FE03      CP      #03             ; task parameter == 3 ? 05C8  CAE005    JP      Z,#05E0         ; yes, skip ahead to handle high score 05CB  11B460    LD      DE,#60B4        ; load DE with player 1 score 05CE  A7        AND     A               ; parameter == 0 ? (1 player game) 05CF  CAD505    JP      Z,#05D5         ; yes, skip next step 05D2  11B760    LD      DE,#60B7        ; else load DE with player 2 score 05D5  FE02      CP      #02             ; parameter == 2 ? 05D7  C26B05    JP      NZ,#056B        ; no, jump back and display score 05DA  11BA60    LD      DE,#60BA        ; yes, load DE with high score 05DD  C37805    JP      #0578           ; jump back and display high score 05E0  3D        DEC     A               ; decrease A 05E1  F5        PUSH    AF              ; save AF 05E2  CDC605    CALL    #05C6           ; call this sub again for the lower parameter 05E5  F1        POP     AF              ; restore AF.  A == 0 ?  are we done? 05E6  C8        RET     Z               ; yes, return 05E7  18F7      JR      #05E0           ; else loop back again GALAX 5155  2231                      ; --- START PROC L2231 --- 5156  2231  FE 03       L2231:  cp      03h 5157  2233  30 18               jr      nc,L224D 5158  2235  A7                  and     a 5159  2236  11 A4 40            ld      de,40A4h 5160  2239  28 1B               jr      z,L2256 5161  223B  3D                  dec     a 5162  223C  20 0A               jr      nz,L2248 5163  223E  3A 0E 40            ld      a,(400Eh) 5164  2241  A7                  and     a 5165  2242  C8                  ret     z 5166  2243  11 A7 40            ld      de,40A7h 5167  2246  18 0E               jr      L2256 5168  2248 5169  2248  11 AA 40    L2248:  ld      de,40AAh 5170  224B  18 AB               jr      L21F8 5171  224D 5172  224D  3D          L224D:  dec     a 5173  224E  F5                  push    af 5174  224F  CD 31 22            call    L2231 5175  2252  F1                  pop     af 5176  2253  C8                  ret     z 5177  2254  18 F7               jr      L224D DK 0307  1C 05                             ; #051C ; 0, for adding to score.  parameter is score in hundreds 0309  9B 05                             ; #059B ; 1, clears and displays scores.  parameter 0 for p1, 1 for p2 030B  C6 05                             ; #05C6 ; 2, displays score.  0 for p1, 1 for p2, 2 for highscore 030D  E9 05                             ; #05E9 ; 3, used to draw text.  parameter is code for text to draw 030F  11 06                             ; #0611 ; 4, draws credits on screen if any are present 0311  2A 06                             ; #062A ; 5, parameter 0 adds bonus to player's score , parameter 1 update onscreen bonus timer and play sound &amp; change to red if below 1000 0313  B8 06                             ; #06B8 ; 6, draws remaining lives and level number.  parameter 1 to draw lives-1 GALAX 2055 205E 215F 21A6 &lt;- DK task 0, add score 21FE &lt;- DK task 1, clear and display (run task 2) 2231 &lt;- DK task 2, display score 22F1 &lt;- DK task 3, draws text to screen 24B7 DK 0008  3A0760    LD      A,(#6007)       ; load A with 1 when no credits have been inserted.  is zero if any credit exist or game is being played 000B  0F        RRCA                    ; any credits in the game ? 000C  D0        RET     NC              ; yes, return 000D  33        INC     SP 000E  33        INC     SP 000F  C9        RET                     ; else return to higher subroutine GALAX 10    0008  3A 07 40    L0008:  ld      a,(4007h) 11    000B  0F                  rrca 12    000C  D0                  ret     nc 13    000D  33                  inc     sp 14    000E  33                  inc     sp 15    000F  C9                  ret DK 0028  87        ADD     A,A             ; A := A * 2 0029  E1        POP     HL              ; load HL with address of jump table 002A  5F        LD      E,A             ; load E with A 002B  1600      LD      D,#00           ; D := 0 002D  C33200    JP      #0032           ; skip ahead 0030  1812      JR      #0044           ; this core sub is actually at #0044 0032  19        ADD     HL,DE           ; HL is now 2A more than it was 0033  5E        LD      E,(HL)          ; load E with low byte from the table 0034  23        INC     HL              ; next table entry 0035  56        LD      D,(HL)          ; load D with high byte from table 0036  EB        EX      DE,HL           ; DE &lt;&gt; HL 0037  E9        JP      (HL)            ; jump to the address in HL GALAX 42    0028  87          L0028:  add     a,a 43    0029  E1                  pop     hl 44    002A  5F                  ld      e,a 45    002B  16 00               ld      d,00h 46    002D  19                  add     hl,de 47    002E  5E                  ld      e,(hl) 48    002F  23                  inc     hl 49    0030  56                  ld      d,(hl) 50    0031  EB                  ex      de,hl 51    0032  E9                  jp      (hl) Also: Interrupt RST 66 uses jump table based on game state (via RST 28) OLDNIN code 1a9623131a9e23131a9e 13FC  1A        LD      A,(DE)          ; load A with a digit of player's score 13FD  96        SUB     (HL)            ; subtract next lowest high score 13FE  23        INC     HL              ; next 13FF  13        INC     DE              ; next 1400  1A        LD      A,(DE)          ; load A with next digit of player's score 1401  9E        SBC     A,(HL)          ; subtract with carry next lowest high score 1402  23        INC     HL              ; next 1403  13        INC     DE              ; next 1404  1A        LD      A,(DE)          ; load A with next digit of player's score 1405  9E        SBC     A,(HL)          ; subtract with carry next lowest high score 237edd7700237edd77 2488  23        INC     HL              ; next HL 2489  7E        LD      A,(HL)          ; load A with table data (EG #3B12) 248A  DD7700    LD      (IX+#00),A      ; store into index 248D  23        INC     HL              ; next HL 248E  7E        LD      A,(HL)          ; load A with table data 248F  DD7715    LD      (IX+#15),A      ; store into index +#15 3F00:  43 4F 4E 47 52 41 54 55 4C 41 54 49 4F 4E 20 21  CONGRATULATION ! 3F10:  49 46 20 59 4F 55 20 41 4E 41 4C 59 53 45 20 20  IF YOU ANALYSE 3F20:  44 49 46 46 49 43 55 4C 54 20 54 48 49 53 20 20  DIFFICULT THIS 3F30:  50 52 4F 47 52 41 4D 2C 57 45 20 57 4F 55 4C 44  PROGRAM,WE WOULD 3F40:  20 54 45 41 43 48 20 59 4F 55 2E 2A 2A 2A 2A 2A   TEACH YOU.***** 3F50:  54 45 4C 2E 54 4F 4B 59 4F 2D 4A 41 50 41 4E 20  TEL.TOKYO-JAPAN 3F60:  30 34 34 28 32 34 34 29 32 31 35 31 20 20 20 20  044(244)2151 3F70:  45 58 54 45 4E 54 49 4F 4E 20 33 30 34 20 20 20  EXTENTION 304 3F80:  53 59 53 54 45 4D 20 44 45 53 49 47 4E 20 20 20  SYSTEM DESIGN 3F90:  49 4B 45 47 41 4D 49 20 43 4F 2E 20 4C 49 4D 2E  IKEGAMI CO. LIM. Nintendo's management knew what it had to do to compete, but the company's modest engineering department had not yet become a video game development studio.  Nintendo turned to Ikegami Tsushinki, which agreed to develop games under Nintendo's name, as well as engineer and manufacture the hardware they would run on.  Nintendo made the cabinets itself and handled all the marketing.  It seemed like a fair arrangement. That problem wasn't as straightforward as it sounds.  Ikegami Tsushinki produced the initial shipment of boards, just as they had done for Radar Scope, but Donkey Kong was a huge hit and Nintendo needed more.  Demand was so high in America that Arakawa began manufacturing new units in Nintendo of America's warehouse. But Nintendo didn't actually own the manufacturing rights to Donkey Kong. Although their game was still a Nintendo product, and the characters, name, and brand all belonged to it, the development contract gave Ikegami Tsushinki the exclusive rights to manufacture and sell boards to Nintendo for 70,000 each.  After the initial order of 8,000 units, Nintendo ceased to buy boards from Ikegami.  Although the contract was unclear with regard to actual copyright of the program code -- still new territory for the law Nintendo didn't see it that way.  Before long, Nintendo had manufactured about 80,000 additional units without Ikegami's involvement, burning the bridge with the company that had developed its biggest hit, and opening themselves up to a bitter legal battle that would drag on for almost a decade. This also left Nintendo without a development team to follow up its smash hit.  Nintendo wanted a sequel, but Ikegami was done with them.  Soon after, Ikegami would go on to anonymously develop the innovative smash hits Zaxxon and Congo Bongo for Sega, contributing to the rise of one of Nintendo's biggest rivals.  Ikegami Tsushinki was clearly an immensely talented team, but its terms were too restrictive for Nintendo's needs, and it needed to find a new partner. DK manual printed in Japan 1981 Galaxian Designer(s) 	Kazunori Sawano Programmer(s) 	Kichi Tashiro SIGS 0028  87        ADD     A,A             ; A := A * 2 0029  E1        POP     HL              ; load HL with address of jump table 002A  5F        LD      E,A             ; load E with A 002B  1600      LD      D,#00           ; D := 0 002D  C33200    JP      #0032           ; skip ahead 00002020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00006020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00006020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00008080  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00001420  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00004020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00002020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00003020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00001020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00001020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00005020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00003020  41 54 41 44 41 54 41 20  87 e1 5f 16 00 19 5e 23  |ATADATA .._...^#| 00004020  f5 f5 f5 f5 f5 f5 f5 f5  87 e1 5f 16 00 19 5e 23  |.........._...^#| 00002020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00002020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00004020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00003220  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00003220  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00010920  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 18 0f  |.o&gt;..g~..._.....| 00001020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001840  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001820  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000820  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 18 0f  |.o&gt;..g~..._.....| 00001020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 0001c060  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 0003a060  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00000060  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00006020  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00008020  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00011380  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 0001b380  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00001820  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00006d60  22 c0 c9 87 e1 5f 16 00  19 5e 23 56 eb e9 f5 e5  |"...._...^#V....| 00016d60  22 c0 c9 87 e1 5f 16 00  19 5e 23 56 eb e9 f5 e5  |"...._...^#V....| 00004040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00013480  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00015480  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00006160  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002020  21 80 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00007220  21 80 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00005020  21 80 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00007080  21 08 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00000040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001220  21 80 60 35 28 f2 e1 c9  87 e1 5f 16 00 c3 32 00  |!.`5(....._...2.| 00002020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 0000c020  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00022040  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00001820  3a 5f 62 a7 28 f2 e1 c9  87 e1 5f 16 00 19 5e 23  |:_b.(....._...^#| 00000320  3a 5f 62 a7 28 f2 e1 c9  87 e1 5f 16 00 19 5e 23  |:_b.(....._...^#| 00000040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001840  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002840  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002020  21 ff 80 35 28 f2 e1 c9  87 e1 5f 16 00 19 5e 23  |!..5(....._...^#| 00000840  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 0000a020  5f 16 00 19 7e c9 00 00  87 e1 5f 16 00 19 5e 23  |_...~....._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000040  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 000036f0  c9 87 e1 5f 16 00 19 5e  23 56 eb e9 e5 1a 4f 13  |..._...^#V....O.| 000088e0  18 bf 87 e1 5f 16 00 19  5e 23 56 eb e9 57 72 23  |...._...^#V..Wr#| 0000b6f0  c9 87 e1 5f 16 00 19 5e  23 56 eb e9 e5 1a 4f 13  |..._...^#V....O.| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00001820  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00000020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 00002020  85 6f 3e 00 8c 67 7e c9  87 e1 5f 16 00 19 5e 23  |.o&gt;..g~..._...^#| 0008  3A0760    LD      A,(#6007)       ; load A with 1 when no credits have been inserted.  is zero if any credit exist or game is being played 000B  0F        RRCA                    ; any credits in the game ? 000C  D0        RET     NC              ; yes, return 000D  33        INC     SP 000E  33        INC     SP 000F  C9        RET                     ; else return to higher subroutine 00000000  3e 00 32 00 a0 c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2...f.:.`..33.| 00008060  3e 00 32 00 a0 c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2...f.:.`..33.| 00001400  3e 00 32 01 c8 c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2...f.:.`..33.| 00004000  3e 00 32 00 a0 c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2...f.:.`..33.| 00002000  3e 00 32 01 a8 c3 00 54  3a 07 60 0f d0 33 33 c9  |&gt;.2....T:.`..33.| 00003000  3e 00 32 00 a0 c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2...f.:.`..33.| 00000100  f3 af 32 1f c0 c3 33 00  3a 04 80 0f d0 33 33 c9  |..2...3.:....33.| 00000010  3a 08 22 0f d0 33 33 c9  00 00 00 00 00 00 00 00  |:."..33.........| 00001000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00001000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00005000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00002000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00002000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00004000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  3e 00 32 01 b0 c3 00 71  3a 07 60 0f d0 33 33 c9  |&gt;.2....q:.`..33.| 00003200  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00003200  3e 00 32 84 7d c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2.}.f.:.`..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  af 32 01 70 c3 32 1a cd  3a 07 40 0f d0 33 33 c9  |.2.p.2..:.@..33.| 00001000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00001820  af 32 01 70 c3 55 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.U..:.@..33.| 00001800  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000800  af 32 01 70 c3 32 1a cd  3a 07 40 0f d0 33 33 c9  |.2.p.2..:.@..33.| 00001000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000040  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00001800  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00002000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00002000  3e 00 32 84 7e c3 30 01  3a 70 60 0f d0 33 33 c9  |&gt;.2.~.0.:p`..33.| 00007200  3e 00 32 84 7e c3 30 01  3a 70 60 0f d0 33 33 c9  |&gt;.2.~.0.:p`..33.| 00005000  3e 00 32 84 7e c3 30 01  3a 70 60 0f d0 33 33 c9  |&gt;.2.~.0.:p`..33.| 00007060  3e 00 32 00 a0 c3 66 02  3a 07 60 0f d0 33 33 c9  |&gt;.2...f.:.`..33.| 00000020  b0 04 00 70 c3 59 1a ff  3a 07 80 0f d0 33 33 c9  |...p.Y..:....33.| 00001000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00001200  3e 00 32 84 7d c3 30 01  3a 70 60 0f d0 33 33 c9  |&gt;.2.}.0.:p`..33.| 00001800  af 32 84 7d c3 de 00 ff  3a 07 60 0f d0 33 33 c9  |.2.}....:.`..33.| 00000300  af 32 84 7d c3 de 00 ff  3a 07 60 0f d0 33 33 c9  |.2.}....:.`..33.| 00000020  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000820  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000020  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  b0 04 00 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |...p.Y..:.@..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00000000  f3 af 32 1f c0 c3 33 00  3a 04 80 0f d0 33 33 c9  |..2...3.:....33.| 00001800  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.| 00001100  f3 ed 56 c3 89 01 ff ff  3a 04 60 0f d0 33 33 c9  |..V.....:.`..33.| 0000c200  f3 ed 56 c3 89 01 ff ff  3a 04 60 0f d0 33 33 c9  |..V.....:.`..33.| 00002000  af 32 01 70 c3 59 1a ff  3a 07 40 0f d0 33 33 c9  |.2.p.Y..:.@..33.|</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/misc/namco-nintendo-connection.md.html</guid>
    </item>
    <item>
      <title>Fuzzing the Z-Machine</title>
      <link>https://8bitworkshop.com/blog/misc/fuzzing-the-z-machine.md.html</link>
      <description>font-weight: bold; background: #3333ff; color:#ccccff; white-space: break-spaces; Playing text adventure games is sort of fun, but takes a lot of brain power. Nowadays we have all this spare CPU capacity going to waste. What if we let the computer solve the game, and we just sit back and watch? We don't even need any fancy neural network, we just need good old brute force. We're going to throw tons of semi-random input at a text adventure and see what happens.  In the security world, this is called *fuzzing*. We're going to target the Z-Machine, a virtual machine interpreter that was developed by Joel Berez and Marc Blank in 1979, and powered Infocom's titles. It's the perfect target for our fuzzing adventures, since it's well-documented and there are plenty of tools and libraries available. The game we're fuzzing is titled *MINI-ZORK I: The Great Underground Empire*. This was an demo version of Infocom's Zork I intended to run from cassette rather than floppy disk. It was essentially an advertisement, given away in an issue of the British Commodore users' magazine "Zzap! 64" in 1990. For those who haven't played Zork, here's the first thing you see when you boot the game: MINI-ZORK I: The Great Underground Empire Copyright (c) 1988 Infocom, Inc. All rights reserved. ZORK is a registered trademark of Infocom, Inc. Release 34 / Serial number 871124 West of House You are standing in an open field west of a white house, with a boarded front door. You could circle the house to the north or south. There is a small mailbox here. The `&gt;` prompt invites users to type commands such as `OPEN MAILBOX` or `GO NORTH` to advance the game. The goal is to "find the treasures of the Great Underground Empire and put them in your trophy case" solving puzzles and defeating enemies along the way. The user manual included with Zork listed examples of potential commands, like `OPEN THE WOODEN DOOR` and `WARLOCK, TAKE THE SPELL SCROLL THEN FOLLOW ME`. However, users were largely on their own in figuring out how to solve a particular puzzle. Verbs like `GET` and `DROP` were obvious, as well as the standard eight compass directions and `UP` and `DOWN` (as well as `IN` and `OUT`.) But users would also have to `ATTACK`, `INFLATE`, and `PRAY`, as well as speak a few magic words that weren't in the user manual. When the game didn't give enough hints to the player, they derisively called this process "hunt the verb". To generate commands, the fuzzer needs to know the list of words accepted by the game, called its *vocabulary*. The Z-Machine defines this list as the *game dictionary*, and it's at a standard location in every game file. The simplest way to generate commands is to take one or more words at random -- one or two words, currently. We don't know which words are verbs and which are nouns, so we end up generating lots of commands like `SEE OOPS` and `DRIVER BELOW`. This is obviously pretty inefficient, since we have to go through N * N combinations (where N is the vocabulary size) to find that special command like `KILL TROLL`. However, we can stack the deck a bit. We scan all the words output by the game, and pick the ones that match our dictionary. We occasionally pick a word from that list instead of the entire dictionary. For example, in the opening text we'd see `NORTH`, `WEST`, `HOUSE`, and `MAILBOX` and be more likely to generate those words. By just issuing random commands, we get a lot of nonsense, which the parser usually rejects: Flailing around like this will take an eternity, though. How do we know which paths are more promising than others? We look for *novel tokens*. The Z-Machine has a PRINT instruction, which outputs text to the console. These are often fragments like "West of House" and "The bottle shatters." We record each of these as a *token*. Whenever we see a new token, we save the current *playthrough* -- the list of commands we executed in the current game. We associate this list with the current token, so that we can (hopefully) regenerate the text by replaying the commands. Each run of the game chooses a specific *goal token*, and thus an associated playthrough. The search algorithm chooses newer tokens more often than older tokens. We don't replay the commands exactly during each game, but we'll throw in some random commands too, and shuffle the order a bit. When we see the goal token, we'll increment a "success" variable, which makes us vary the command list less often. When this variable gets high enough, we mark this token "stable", since we have a predictable playthrough that generates it. The paths we take through the game aren't often efficient. Here's one list of commands we used to generate the token "Wheeeeeeeeee!!!!!": curse, art, body gate, incant count, the, the egg, repent, from the, the consum, what, leathe, trap- see, breath here, what intnum, about here, leathe guideb, about, about here, pot, here, see, here about, about, self, here about, mangle, see, rug, the, reply, elvish, say, stilet beetle, say toss, pray, gate about, what bolt, guideb, wooden, say knock, say sit, trail and, here, pray leathe, intnum, one, pray one, jump All we really had to do is type the last command, `JUMP` (or `DIVE`). But the search algorithm doesn't know which of the preceding commands are required to output "Wheeeeeeeeee!!!!!" So we *reduce* the playthroughs -- make them as short as possible. Whenever we see a token, we'll replace the associated playthrough with a shorter list of commands, if possible. This gets us to the goal token faster, giving us more turns to experiment after reaching the goal. A lot of tokens like "Wheeeeeeeeee!!!!!" aren't interesting, in that we can generate them in a single turn at the start of the game. By reducing their command lists, we can eventually prove this to be true, and thus remove them from the list of potential goal tokens. Because we have access to the Z-Machine internal state, we can use things other than the textual output to guide our search. For example, we can record when an object moves from room to room, or when an object's property flag changes. We call these *VM tokens*, and we record them along with textual tokens: We need these because the textual output doesn't tell us the whole story. For example, picking up a sword and a lamp both generate the token "Taken." The VM token tells the search algorithm when a novel VM state is reached, for example when the player moves to a new room, or an object is picked up or discarded. Exploring the game state is a pretty slow process. One of the first tasks in the game is to kill a troll who blocks your path. However, the player has to have previously picked up a sword in the house above. To short-circuit the search process, we randomly *hack* the Z-Machine, changing game state in ways we've seen previously. For example, we might randomly move the sword to the player's hand, allowing the `STAB` command to succeed. We'll only hack with stable tokens, so that if we can reliably repeat the player picking up the sword, we'll allow hacking of the sword into the player's hands. Then we'll merge the commands used to pick up the sword into the commands used to descend into the dungeon, hopefully figuring out that we need to attack the troll. The troll example is particularly diabolical, because it usually takes multiple blows to finish off the troll, each attack generating a random result. Since our algorithm prefers shorter playthroughs, it's more likely to be optimistic about our fighting abilities. After 530,000 playthroughs and 10,600,000 commands (200 commands per game) we finally figure out how to attack the troll: north, east, open window, into, west, light, lift trap, small hi, get, west, light, tug large, lift trap, down, north, stab We've got a few superflous commands, and we haven't yet figured out that we have to hit him multiple times, but we'll get there. The search algorithm doesn't know the difference between picking up objects, dropping objects, and moving the player from room to room. The only way it determines forward progress is by seeing novel tokens. This leads the search algorithm to quickly develop a taste for ... murder! Killing the player, specifically, because it's so easy -- you just type `ATTACK`: Poof, you're dead! Well, you probably deserve another chance. I can't quite fix you up completely, but you can't have everything. Forest Edge Paths lead into the forest to the west and northwest. Also, a well-marked path extends east. In Mini-Zork, the first death doesn't end the game, but the player is teleported to another location, and your possessions are scattered. To the search algorithm, death is just an object moving from one room to another, generating novel tokens along the way. This fascination leads to the exposure of other funny bugs in the game, like the player being able to throw their own hands into a river. The game keeps a score of 0 to 350 points, based on solving puzzles and collecting treasure. When the player dies, the score goes down by 10 points. We can use score as a heuristic, but this might overly dissuade risky behavior -- like going into a dark location, or fighting trolls. The search algorithm also gets interested in stuff that the player doesn't see, like NPCs moving between rooms. For example, the token `@mv_112_37` represents the thief moving to a specific room. The search algorithm manages to reproduce this token by issuing the `Z` or `WAIT` command repeatedly, waiting for the thief to reach the target room. It also loves to pick up and drop objects in different locations, because each object movement is a new token. Who knows? Maybe dropping that leaflet in the Forest Path will win the game. (Narrator: It won't.) Fuzzing invaribly exposes bugs in a program, and this game is no different, although it's fairly resiliant. It figured out how to generate the garabage word "Clrthatrqdc" at the start of the game: With a   Clrthatrqdc!?! This is probably an uninitialized variable pointing to non-textual data. The Z-Machine's compressed text encoding favors alphabetic letters, which is why you don't see as much random garbage as when trying to print a binary file as ASCII. To win the game, we have to haul our loot back to the trophy case and place each item inside. It'll take a long time for our simple search algorithm to stumble upon this behavior, especially given its tendency to waste time moving objects from room to room. Making the algorithm more complicated takes time away from the random exploration phase, so we have to be judicious when adding features. And we want to avoid *a priori* knowledge of the game -- in other words, we only want to cheat a little bit. If you want to experiment, check out the [source code on GitHub](https://github.com/sehugg/jszm/blob/master/search.js), which uses Daniel Lehenbauer's [JSZM](https://github.com/DLehenbauer/jszm) interpreter. Plenty of [games](http://www.ifarchive.org/indexes/if-archiveXgamesXzcode.html) are available (only up to Version 3 supported.) Also see [The Z-Machine Standards Document](https://www.inform-fiction.org/zmachine/standards/z1point1/index.html) by Graham Nelson, who's been working with the Z-Machine for a couple of decades. And should [8bitworkshop](https://8bitworkshop.com/) support the Z-Machine one day? Let me know!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/misc/fuzzing-the-z-machine.md.html</guid>
    </item>
    <item>
      <title>Compiling a C-64 Emulator to WebAssembly</title>
      <link>https://8bitworkshop.com/blog/misc/compiling-emulators-to-webassembly-without-emscripten.md.html</link>
      <description>We use a variety of emulators in [8bitworkshop](https://8bitworkshop.com/). Many of them, like most of the Z80 emulators, are written from scratch in JavaScript directly against our Platform API. This facilitates deep introspection into the emulator state, which comes in handy for things like debugger support and CPU visualization. To save effort, we also integrate a couple of open source emulators. Atari 2600 support is courtesy of [Javatari](https://github.com/ppeccin/javatari), and NES support is courtesy of [JSNES](https://github.com/bfirsh/jsnes). Each of them requires significant patching to expose hooks for the extra features the IDE supports, like breakpoints and bus-monitoring. We can also use MAME, compiling it to WebAssembly using [Emscripten](https://emscripten.org/). The trouble is that it's a bit heavyweight and monolithic, and wants to be treated as an application, not a library. Due to the way it's architected, interacting with the debugger via JavaScript [isn't really feasible](https://github.com/mamedev/mame/issues/3649). Even simple things like re-loading the ROM require a ton of Lua scripting. There are lots of open-source emulators written in C. What if we could use C emulation code as a library, and interact with it from JavaScript? It turns out we can use WebAssembly to do this. At first, we might naturally consider using Emscripten. There are two methods for binding Emscripten-compiled C++ code to JavaScript, and However, it turns out we don't even need these frameworks, or even the full Emscripten wrapper. We can compile directly to WebAssembly using Clang alone. We're going to emulate the Commodore 64. There are plenty of emulators, but which to choose? The [chips](https://github.com/floooh/chips) library contains no dependencies except a few standard library functions, so it's a good candidate. Its README describes it as: We just need a single C file to tie everything together. In it, we include all of the files required for the C64 emulation. We first define `CHIPS_IMPL` which instructs the preprocessor to include the function implementations, not just the definitions: We also need a few standard library functions, like `assert()`, `malloc()`, `free()`, `M_PI`, `memset()`, `memcpy()`. It's easier to roll our own (or rip off) the few functions we need. For example, here's our very simple `malloc()` function: extern unsigned char __heap_base; unsigned char* bump_pointer = &amp;__heap_base; void* malloc(unsigned long n) { void free(void* p) { To smooth out the interface between JavaScript and C, we define a bunch of wrapper functions in `c64.c`. C exports functions unless told otherwise, so all are available to the JavaScript program via the module's `exports` property. For example, `machine_init` allocates a `c64_t` struct type and initializes the emulator with defaults. c64_t* machine_init(char* bios) { We chose the `machine_` prefix so that we can potentially emulate other systems by just swapping out the WebAssembly file. From JavaScript, we first load the BIOS binary: var biosResponse = await fetch('wasm/'+this.prefix+'.bios'); var biosBinary = await biosResponse.arrayBuffer(); const srcArray = new Uint8Array(biosBinary); Then we allocate a BIOS buffer in the WASM memory space with our own C `malloc()` function. const cBIOSPointer = this.exports.malloc(0x5000); This returns a pointer, which is just an integer representing an offset to the WASM memory space. The entire WASM memory space is exposed to JavaScript via the `memory.buffer` export, so we can map it to a JavaScript typed array: const destArray = new Uint8Array(this.exports.memory.buffer, cBIOSPointer, 0x5000); destArray.set(srcArray); Now we can use the pointer returned by `malloc()` to call `machine_init`, which returns a pointer to a `c64_t` emulator struct: this.sys = this.exports.machine_init(cBIOSPointer); The internal `machine_hardreset` does the minor heavy lifting. It allocates a pixel buffer, pointers to the BIOS segments, and defines an audio callback function: void machine_hardreset(c64_t* sys) { Now we need to compile all this stuff to WASM. First we install a recent [Emscripten SDK](https://github.com/emscripten-core/emsdk) and run `./emsdk_env.sh` to set our command interpreter's environment variables. We compile to WebAssembly using Clang directly, a technique inspired by Our Makefile looks like this: CLANG="$(EMSDK)/upstream/bin/clang" test: wasm/c64.wasm wasm/c64.wasm: wasm/c64.c We type "make" and hey, it worked! We built a WASM file, but there's no Emscripten boilerplate .js file: We can test our WASM module with a simple Node `test.mjs` program. We need to use experimental module support to include the WASM file like a regular module. It runs the emulator for a few cycles and outputs a screenshot: import * as c64 from './c64.wasm'; c64.memory.grow(32); import * as fs from 'fs'; const bios = fs.readFileSync('wasm/c64generic.rom') const cArrayPointer = c64.malloc(0x5000); const cArray = new Uint8Array( cArray.set(bios); const sys = c64.machine_init(cArrayPointer); c64.machine_reset(sys) c64.machine_tick(sys); c64.c64_exec(sys, 100000); const pixels = new Uint8Array( fs.writeFileSync('test.rgba', pixels); The emulator interface doesn't support everything yet -- the CPU/memory bus hooks that provide data for the Memory/CRT Probe views aren't implemented. We can easily make WASM files for other platforms supported by the chips library, for example the ZX Spectrum, Acorn Atom, and others. We could also use the C interface to support other emulator libraries, as long as they don't use too many standard library functions.</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/misc/compiling-emulators-to-webassembly-without-emscripten.md.html</guid>
    </item>
    <item>
      <title>Sincere Flattery in the Early Arcade Industry</title>
      <link>https://8bitworkshop.com/blog/history/sincere-flattery-arcade-industry.md.html</link>
      <description>title:  "Sincere Flattery in the Early Arcade Industry" date:   2017-04-27 11:59:03 -0400 categories: history image: /blog/images/littlebrickout.jpg The pioneering days of video games saw a tremendous amount of innovation, but also a lot of unabashed appropriation. Designers were under pressure to develop novel experiences with unfamiliar technology in a new medium, and they often bet conservatively by tweaking a successful design rather than creating out of whole cloth. From the first video game in 1962, there is a clear path of derivation to the Cambrian explosion of 1979, a rapid era of progress in video game design that created the modern arcade classics we know and love. These are some of the platforms I describe in my book *[Making 8-bit Arcade Games in C](https://www.amazon.com/dp/B01N4DSRIZ)*. The Bronze Age Begins Video games were invented in academia, but refined in industry. The first inventions generally recognized as video games were *Tennis for Two*, developed by William Higinbotham at Brookhaven National Laboratory in 1958, and *Spacewar!* by Steve Russell and others at MIT in 1962. In 1971, Bill Pitts and Hugh Tuck developed a coin-operated version called *Galaxy Game*. Powered by a single PDP-11, the final version could play games on four monitors simultaneously. Despite its popularity at the Stanford student union, it never made back the $65,000 development cost, and did not progress beyond the prototype stage. While Pitts and Tuck were focused on gameplay, Nolan Bushnell and Ted Dabney had been trying to reduce the cost enough to manufacture. They decided to make their own hardware which was powerful enough to run a single monitor, and partnered with Bill Nutting to manufacture it as *Computer Space*. Ralph Baer, Atari and PONG Soon afterwards, the Magnavox Odyssey was released with a ping-pong game developed by Ralph Baer. Bushnell had played it previously, and in 1972 released a similar game under the newly-formed Atari label called *PONG*. This did not go unnoticed by Magnavox, who eventually forced Atari into a licensing deal, of which Atari got the better end. It was quickly imitated by several manufacturers, including Bushnell's former partner Bill Nutting. Several years later, Atari released *Breakout*, a brick-busting game which was perhaps inspired by another *PONG*-lookalike Steve Wozniak worked on a design for *Breakout* that would never be used. But the experience working on the game inspired him to add color graphics, paddles, and sound to the Apple II computer design. The system diskette included a game called *Little Brick Out* written in his own BASIC interpreter, originally called "Game BASIC". Gremlin Industries Later known as Sega/Gremlin and then just Sega, this amusement company started making video games in 1976. Their first game *Blockade* was a big hit, inspiring many clones, and years later, the light cycle sequence in the movie *Tron*. But the flattery was not well received. They were one of the first game manufacturers to use a CPU -- the Intel 8080 -- and one of the first to use RGB color monitors. Their "VIC Dual" system was reused for several different games. Space Invaders Meanwhile in Japan, a young engineer named Tomohiro Nishikado had developed a Pong clone *Elepong* for Taito Corporation. He had seen Atari's Breakout, and its "level clearing" gameplay inspired the descending wall of aliens in his 1978 game *Space Invaders*. The hardware for Space Invaders is more-or-less compatible with Midway's *Gun Fight* -- a game which Nishikado designed but was adapted for the Intel 8080 CPU by Dave Nutting (Bill Nutting's brother). This hardware had been used for previous monochrome Midway games. In addition, the *Space Invaders* code contains a sprite drawing routine also found in *Gun Fight*. Since the 8080 didn't have a barrel shifter, this routine uses the onboard Fujitsu MB14241 chip to shift the sprite's bytes by arbitary amounts before writing them to the frame buffer: Asteroids and Vector Graphics Vector graphics didn't start with Atari, but with an MIT student named Larry Rosenthal. He had also seen *Spacewar!* at Stanford, and recreated it with a homemade CPU and a vector display adapted from a black-and-white TV. Cinematronics purchased the technology and released the game as *Space Wars* in 1978. Atari developed its own vector technology, but was still looking for a new game concept, having already done *Computer Space*. They released *Lunar Lander* in 1979, but the game's concept was seeded ten years prior. written by a high-school student named Jim Storer. A DEC employee named David Ahl later converted it into BASIC, later including it in his very popular *101 BASIC Computer Games* books. In 1973, DEC contractor Jack Burness created a graphical version to promote its GT40 vector graphics terminal. This is likely the version that inspired Atari's game. Atari's next vector game, *Asteroids*, would be inspired by multiple games. Lyle Rains combined the two-dimensional approach of *Computer Space* with the eliminate-all-enemies gameplay of *Space Invaders*. Ed Logg used *Spacewar*'s basic control scheme for the ship, including the hyperspace button. Arcade operators eventually grew tired of the fussy and expensive vector monitors, and no new vector games were produced after 1985. But these classic games inspired countless others. Galaxian The marching columns of aliens in Namco's *Galaxian* were undeniably influenced by *Space Invaders*. Designer Kazunori Sawano also cites the recently-released *Star Wars* movie as having a "huge impact" on the team. Galaxian would also spawn many imitators, but its lasting contribution is its hardware design, which pushed the limit of video game designs in 1979. At its core is a Z80 CPU at 3.072 MHz. The graphics system featured RGB graphics and multicolor hardware sprites overlapping a 28x32 tiled background. The designers would reuse the same PCB (printed circuit board) for *King &amp;amp; Balloon*. Other companies like Konami licensed the video hardware to make games like *Scramble* and *Frogger*. The same basic tiles-and-sprites system would be used for many other titles -- *Pac-Man*, *Dig Dug*, *Xevious*, etc. Williams and what if the game universe was larger than a single screen? This led to *Defender*'s scrolling planetary surface. Williams' games featured a 36 KB video frame buffer -- in 1980, that was a lot. A pair of "special chips" acted as a primitive 2D GPU, quickly blitting sprites to the frame buffer. The Post-Invaders Era After *Pac-Man* fever had replaced *Space Invaders*, arcade game designers looked beyond the shoot-em-up for inspiration. Yet games like *Galaga*, *Tempest*, and *Gyruss* breathed new life into the old fire-button formula. Hardware designers were busy too, adding more colors and resolution, hardware sprite scaling, speech and FM audio synthesis. But the gaming platforms of the late 1970s would inspire a generation of programmers and designers. In my new book *[Making 8-bit Arcade Games in C](https://www.amazon.com/dp/B01N4DSRIZ)*, I describe five of these unique platforms (VIC Dual, Midway 8080, Galaxian/Scramble, Atari Vector, and Williams), and how to program them in C using the &lt;a href="http://8bitworkshop.com/"&gt;8bitworkshop IDE&lt;/a&gt;.</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/history/sincere-flattery-arcade-industry.md.html</guid>
    </item>
    <item>
      <title>8bitworkshop IDE User Manual</title>
      <link>https://8bitworkshop.com/blog/docs/ide.md.html</link>
      <description>To start the IDE, open https://8bitworkshop.com in your web browser and click **Continue to 8bitworkshop IDE**. For best results, use a recent version of Mozilla Firefox, Google Chrome, or Apple Safari. The 8bitworkshop IDE supports a number of different hardware platforms. You can switch between them using the pulldown to the right of the main menu. The IDE is packaged with several example programs for each platform. To the right of the menu icon, you can access a Project Selector drop-down menu that allows you to select a file to load. You can edit these files as much as you want --- all changes are persisted in browser local storage and they'll be there if you close the browser tab and come back. If you want to restore one of the example files back to its original condition, select **File &gt;&gt; Revert to Original...** from the menu. To start from scratch, select **New Project...** from the menu. Type in the name of your new file, typically with a `.c` extension for C source files. You can also write 6502 assembler with the `.asm` extension. Each platform has its own virtual file system in the browser, so any edits or new files will only be visible to the current platform. The IDE includes built-in emulators for all platforms, which run  your code on simulated hardware. To control the game, first click the emulator screen to gain focus. The IDE will show the keyboard commands used by the current platform. Some platforms also support gamepads. The IDE also includes C compilers and assemblers for most platforms. They run in the web browser, along with a web-based text editor. Each time you make a change to the code, it's immediately compiled. If there are no errors, the emulator is restarted with the new ROM image, allowing you to see code changes near-instantly. The IDE includes a simple debugger which allows you to step through machine code instructions, view memory, and start and stop the program. The buttons at the top of the screen perform several debugging functions: These buttons may not be available on every platform: Whenever the IDE hits a breakpoint or is single-stepped, a debug window appears in the lower-right of the screen. This shows the internal state of the CPU, including all registers and flags. You can click the links at the bottom to see additional info. You can export and import files, share playable links and videos, sync projects to GitHub, and pull projects from GitHub. If you plan to clear cookies or use different browsers or computers, you may need to export your work and import it. To save your files outside of browser cache: 1.  Select **Download** from the menu. 2.  Choose an option: 3.  When prompted, select a location on your computer and save the file. To import source files back into the browser: You can share playable links and videos (seven second animated GIFs) with others. Playable links actually contain the project code inside the URL. This allows you to share your work without storing it remotely or worrying about the permanence of the URL. One caveat, however, is that some browsers may not support the URL length. To share a playable link: 1.  From the menu, select **Share**. 2.  Select **Share Playable Link...**. A pop-up appears with link 3.  Select **Copy Direct Link** to copy the link to your clipboard or 4.  Click **Close** to exit the window. To share a seven second animated GIF: 1.  From the menu, select **Share**. 2.  Select **Record Video...**. You'll see the emulator window 3.  Right-click on the Preview and choose **Save Image As...** and save 4.  Click **Close** to exit the window. You can now sync 8bitworkshop projects with GitHub source code repositories. From the 8bitworkshop IDE, you can import projects from GitHub repositories, publish your projects, and push/pull to/from GitHub repositories you have access to. When you publish or push your projects to GitHub, 8bitworkshop pushes your code and a compiled ROM file to your repository. To connect your GitHub account: 1.  From the menu, select **Sync &gt;&gt; Sign in to Github...** 2.  When prompted, enter your GitHub username and password. To import a project from a GitHub repository: 1.  From the menu, select **Sync**, then choose **Import Project from 2.  In the pop-up that appears, enter the URL of the repository you want To close the project and access other projects and files: To access the project later: To remove a GitHub repository from local storage: To publish an 8bitworkshop project to a GitHub repository: 1.  From the menu, select **Sync**, then choose **Publish Project on 2.  When prompted, add a project name and description. The username will 3.  Choose the visibility of the published project by choosing 4.  Select a license type. 5.  Click **Upload Project**. If you've already logged into GitHub, the To push changes to a GitHub repository: 1.  From the menu, select **Sync**, then choose **Push Changes to 2.  When prompted, enter a commit message and then select **Push To pull changes from a GitHub repository: 1.  From the menu, select **Sync**, then choose **Pull Latest from 2.  When prompted to pull from repository and replace all local files,</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/docs/ide.md.html</guid>
    </item>
    <item>
      <title>Retargeting a C Compiler to 6502</title>
      <link>https://8bitworkshop.com/blog/compilers/retargeting-a-c-compiler-to-6502.md.html</link>
      <description>I've written before about [cc65](cc65-optimization.md.html) and some of its optimization challenges. It's a stable compiler with a robust toolchain, but its code generator doesn't full advantage of the 6502 when performing 8-bit operations. It places function parameters and many local variables on a separate stack, which requires many calls to helper functions. I've done a [survey of 6502 high-level languages](higher-level-6502-programming.md.html), and while many are intriguing, none have the stability and C compatiblity of cc65. So what's so hard about the 6502? What's keeping us from just retargeting a modern C compiler, bringing its powerful optimization routines to 6502? Well, it's complicated. Like, really complicated. LLVM is the dominant compiler backend library, and there's [documentation](https://llvm.org/docs/WritingAnLLVMBackend.html#register-set-and-register-classes) on how to write a LLVM backend. However, many of the instructions read like "draw two circles, then draw the rest of the damn owl". LLVM is a freakin' huge library, and backends tend to be [complex](https://jonathan2251.github.io/lbd/). It wasn't designed for 8-bit systems like the 6502 where stack access is cumbersome and registers are scarce. But what if there were something already in the 8bitworkshop pipeline, right under our nose? Yes, it's SDCC, the Small Device C Compiler, the same one we use for Z80! What if we could retarget it to the 6502? The benefit of SDCC is that it already supports a handful of microcontrollers more constrained than the Z80. The Motorola/Freescale [HC08](http://hc08web.de/usb08/files/cpu08r2.pdf) is similar to the 6502 in some ways. It has an 8-bit accumulator and two 8-bit index registers. It also differentiates between direct (0-255, or zero page) and extended (0-65535, or absolute) addressing modes. Might this be a good start for our own 6502 backend? Let's find out. We'll use this simple C program to compare compilers: bool get_pixel(uint_fast8_t x, uint_fast8_t y); void set_pixel(uint_fast8_t x, uint_fast8_t y); void fill_line_left(uint_fast8_t x, const uint_fast8_t y) { Caveat: This test program is from a [research paper](https://link.springer.com/content/pdf/10.1007%2F978-3-642-37051-9_1.pdf) about register allocation written by SDCC's maintainer, so we might be cherry-picking a bit. Let's see how CC65 compiles this: L000E:  lda     (sp),y L0003:	jmp     incsp2 CC65 stores its parameters on the stack, requiring an expensive indirect `(sp),y` instruction. Note the `jsr pusha` subroutine calls, which take about 40 cycles each, used to push parameters on the stack for `get_pixel` and `set_pixel` function calls. HC08 is the backend on which we'll base the 6502 backend, so let's see how it does: _fill_line_left: 00104$: 00102$: It's a lot smaller than the CC65 version, and has no indirect loads or parameter pushes. This backend passes two 8-bit parameters in the A and X registers -- additional parameters are generally passed in static locations. It also looks pretty similar to 6502 code, doesn't it? One might be tempted to convert this directly to 6502 without mucking about in the backend. SDCC has a peephole optimizer that we can configure to translate to 6502 code. For example, HC08's TST instruction can be converted to 6502's BIT instruction: Some HC08 instructions aren't directly mappable. For example, indirect load of X requires a zero-page pointer: Going down the rabbit hole, we'll discover that this approach isn't workable. HC08 isn't exactly like 6502: So now we'll go mucking around in the compiler source. Hacking the HC08 backend to produce 6502 code is easy, right? Turns out there is a lot involved in "making it do the other thing", e.g. emitting working 6502 code: After all that and more, we finally get output from the experimental SDCC 6502 backend: _fill_line_left: 00102$: What kind of obstacles did we run into? If I started from scratch, I'd think about writing a 6502 code generation layer before touching the SDCC backend, that would: You can download the experimental fork of SDCC with 6502 support here: https://github.com/sehugg/sdcc-m6502 Look at the [manual](http://sdcc.sourceforge.net/doc/sdccman.pdf) (PDF) for build instructions.</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/compilers/retargeting-a-c-compiler-to-6502.md.html</guid>
    </item>
    <item>
      <title>New Frontiers in High-Level 6502 Programming</title>
      <link>https://8bitworkshop.com/blog/compilers/higher-level-6502-programming.md.html</link>
      <description>Programming directly in 6502 gets a little fiddly, so a higher-level language can make things easier. There have been many [attempts](https://dwheeler.com/6502/) to tame the 6502 to make programming more palatable. Interpreted languages like BASIC, FORTH, and Pascal were popular back in the day, and Infocom games had their own custom [VM](http://www.ifwiki.org/index.php/Z-machine) to run on many platforms. But programmers are a stubborn bunch, and want speed as well as usability. One approach is to just write a really powerful macro assembler that almost looks like a high-level language. In the 1980s, Lucasfilm developed [Macross](https://www.pagetable.com/?p=848)  as "an assembler for people who hate assembly language". More recently, [NESHLA](http://neshla.sourceforge.net/) is targeted at NES development, but hasn't seen much new development since 2005. It's been more than 40 years since Chuck Peddle sold the first 6502 samples out of a jar at a trade show. Intrepid developers are still making new languages for the CPU. Here's a quick survey of some that have been active in the last few years: the 6502, but it's not perfect. The C language is difficult to optimize for a machine with only three 8-bit registers, and so code quality is suboptimal. However, it has a complete set of libraries, and is a clear choice for building code for Atari, Apple, Commodore, Oric, NES, and many other systems. the Amsterdam Compiler Kit and inspired by Ada. The compiler operates in several independent phases, so that it can build itself on small systems like the Z80 and 6502. Because it forbids recursion, it doesn't need stack frames, and thus can arrange all variables in global memory. The syntax should be familiar to fans of Pascal, and the language even supports inheritance -- no `for` loops yet, though. assembler with static analysis. It gives the programmer instruction-level control, but helps to catch common mistakes -- use of uninitialized flags or registers, out-of-bounds array accesses, and subroutines unexpectedly trashing registers. As such, routines have to explicitly define their inputs, outputs, and side-effects, for example: looks like C, but really isn't. There are specific keywords for zero-page variables and page-aligned arrays. Function calls are limited to three byte-sized arguments, and only the first argument may be a complex expression. Any more than that and you have to explicitly `push` and `pop` arguments on and off the stack, or use "inline" arguments. It looks promising, as there aren't many high-level languages efficient enough to target the Atari 2600. Speaking of which... The language is classic C with some limitations and a few modifications to allow it to optimize better for 6502 assembler. It's still in beta, but looks promising. is a mid-level programming language targeting 6502-based, 8080-based and Z80-based microcomputers.  Unlike in high-level languages, operators in Millfork have limited applicability.  Not every well-formed expression is actually compilable.  Most expressions involving single bytes compile, but for larger types usually you need to use in-place modification operators. Calling conventions pass in registers or in static locations on 6502/Z80 platforms. It has a "multi-pass whole-program optimizer". It requires that the programmer manage their own registers. For example, instead of saying `hp -= 10` you'd write `hp = a = hp - 10`. It supports 6502 and has NES and C64 libraries. Fred Quimby released [batariBasic 1.0](http://bataribasic.com/) in 2007, and recently [others](https://github.com/sehugg/batariBasic) have been trying to resume development. This is a BASIC-inspired language wholly targeted at the Atari 2600 platform, and as such it has a lot of platform-specific quirks. For instance, to define a 8x8 player sprite you might do this: The strong suit of this system is the availability of various "kernels" that can generate different combinations of playfield and sprite graphics without the pain of assembler. There is a strong around the language, and many full games have been published. There's even [Visual bAtariBasic](http://www.randomterrain.com/atari-2600-memories-batari-basic-vbb.html) under developement which integrates various visual editors. language which is currently targeted to Apple I/II/III platforms. After trying to make a 6502 Java interpreter, the author took the lessons learned and designed his own language and bytecode scheme. PLASMA works with dynamically linked modules, so the runtime system is highly integrated with the host platform. There's even support for JIT compilation on some platforms. is an ALGOL-like language and programming environment for Atari 8-bit computers, released in 1983. The author has recently released the source code and it's enjoying a resurgence of popularity, as hobbyists are fixing bugs, writing documentation and extending the software. runs Applesoft programs, but compiled instead of interpreted! This is supposed to speed things up 5-30x, but there's no floating point support (an approach taken by vintage Applesoft compilers like Dustmop created the Lisp-y [CO2](https://github.com/dustmop/co2) compiler to make the NES game ["What Remains"](https://iodinedynamics.com/whatremains.html). It supports bank-switched code, static local variable allocation, structured conditionals, and has a simple peephole optimizer. It's built on top of [Racket](https://racket-lang.org/). is a 32-bit Turbo Pascal-compatible compiler for Atari XE / XL. For homebrew game developers, using a non-standard language is just part of living on the edge of retro technology. These dev tools are still a little rough around the edges (with the possible exception of cc65) but ready for experimentation and improvement. Who knows, you might even see some of them one day on [8bitworkshop](http://8bitworkshop.com/)!</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/compilers/higher-level-6502-programming.md.html</guid>
    </item>
    <item>
      <title>Optimizing C array lookups for the 6502</title>
      <link>https://8bitworkshop.com/blog/compilers/cc65-optimization.md.html</link>
      <description>Most of the platforms in the IDE that are powerful enough to support a C compiler are Z80-based. The Z80 isn't the easiest target for C, but at least it has a lot of registers. While the 6502 only has three 8-bit registers, the 6502 has strengths the Z80 doesn't, as we'll see here. Let's compare the two dominant C compilers for these CPUs. We'll compile a function with the CC65 C compiler for the 6502, and then with the SDCC We'll call the function `getValue()`: int arr16[128]; int getValue(int index) { This function just looks up a value in a array of 16-bit ints, truncates the result to 8 bits, then divides it by 2. We'll first compile it with the default flags for both compilers: L0004:  jsr     incsp2 The 6502 version is a little more verbose here, compiling to 41 bytes vs. 31 bytes for Z80. One big difference: SDCC turns on most optimizations by default. That's not fair, so let's see what optimizations we can activate for CC65. We'll compile it again, but this time we'll pass the `-O` flag to CC65. We'll try to get the Z80 version even smaller by passing `--opt-code-size` to SDCC: The 6502 version is a lot smaller, down to 18 bytes! The Z80 version is only a little smaller due to the replacement of the stack frame setup with a function call. What happened here to make the 6502 version so small? The pedigree of CC65 goes back to 1980 and the As a result, its optimization methods depend highly on This is a method of scanning code linearly to look for patterns, then rewriting those patterns to be more efficient. One such pattern is one I recently added in It looks for 16-bit array lookups of the form: array16[index &amp; 0x7f]    // or index &lt; 0x7f CC65 defers most optimization until after code generation. The pseudocode before optimization looks more-or-less like this: AX = index AX = AX &amp; 0x7f AX = AX &lt;&lt; 1 AX = AX + address(arr16) AX = read16(AX) AX = AX &gt;&gt; 1 return AX This may not look like a lot of code, but `AX` is a 16-bit value (actually the AX register pair) and manipulating 16-bit values is expensive on the 6502. We need to find a way to reduce it to an 8-bit problem. The key here is the `index &amp; 0x7f` mask. This guarantees that the array index will be less than 128. Each array element takes two bytes, so we only have to index up to 256 bytes of data -- enough for 8 bits. Instead of computing a 16-bit offset for the array, we can use the 6502's The pseudocode now looks like this: A = index       // lda (sp),y A = A &lt;&lt; 1      // asl a Y = A           // tay A = arr16[Y]    // lda _arr16,y A = A &gt;&gt; 1      // lsr a return A        // jmp incsp2 Because we're dealing mainly with 8-bit values, this code becomes much smaller and faster. Note that we don't even need the `index &amp; 0x7f` mask anymore, because the `asl a` instruction takes off that high bit for us. Let's compare the non-optimized 6502 output with the optimized version: L0004:  jsr     incsp2                  jmp     incsp2 The Z80 doesn't have a equivalent addressing mode. To do a fast 8-bit table lookup, we have to align our table to a 256-byte page. Then we can stuff the index in the lower 8 bits of a 16-bit register pair. The result would look sort of like this: The 6502 doesn't require page alignment, so it has the edge here in optimizing this case. The Z80 is better at other things, like dealing with If you want to play with the CC65 C compiler, you can do so right now in the [8bitworkshop IDE](http://8bitworkshop.com/) using the venerable  Apple II platform (with maybe more coming in the future!)*</description>
      <author>info@8bitworkshop.com (8bitworkshop)</author>
      <guid isPermaLink="false">https://8bitworkshop.com/blog/compilers/cc65-optimization.md.html</guid>
    </item>
  </channel>
</rss>
