• Project Results

    Louis Paul6 days ago 0 comments

    Now that the RetroChallenge is over, it's time to detail the project results, what was my expectactions about it, and what I learned when making the project.

    Before doing this project, I had experience with 8086 assembly, from the previous project of Fungesector which I made last year ago, and 6502 assembly, from a course of making a NES homebrew game.

    For the first days of the project, I was using the 8080 syntax to write the 8080 code. I found the 8080 mnemonics confusing and inconsistent, then I found out that the zasm assembler supported the Z80 syntax, then I switched to that syntax.

    For the project results, I managed to create the basic gameplay of the game, with the screen states and tile actions. A thing I forgot to implement which would the helpful is an highlight to indicate where the tile was last spawned.

    My expectations for this project, which I haven't had the time to implement, were to add more stuff to the game, like a 2 player mode, a high score screen, and testing the binary code on other games based on the same hardware.

    I learned about the memory map of the RAM, Video RAM, how to read the coin input, 1 player input and the arrows, the similarities of 8080 and Z80, how to debug the binary on MAME, and some other stuff.

    Writing a game purely in 8080 assembly without using an high-level language is not easy. You have to implement the subroutines from scratch, I'm still working on the code, refactoring it, finding bugs and attempting to correct it.

    I was supposed to publish this project log on November 1st, but I had the problem of procrastination. So my strategy is to launch the game as a prototype, and a proof of concept that it's possible to write it on an arcade hardware from 1975 (the year where Gun Fight was launched).

    I'll post the source code of the project to GitHub (link here), I'm just polishing the code a bit more, for the case I might extend and improve in the future. Like last year, I hope someday to show a more complete version of the game, with the winning screen.

  • Last Days for the End

    Louis Paul10/30/2025 at 04:08 0 comments

    The RC2025/10 is near the end, I'm still working on the 2048 game. I managed to implement the tile shifting when you press an arrow key. I still need to implement the tile merging and score counting.

    For the tile shifting, I created one subroutine to shift the rows of the grid for left and right arrow, and another subroutine to shift the columns of the grid for up and down arrow. I also implemented a timer when the game is over, to return to title screen to insert a coin again.

    One interesting thing of the 8080 and Z80, is that they have conditional subroutine call in the form of CALL f, nnnn, and conditional return in the form of RET condition. That means you can have more efficient control flow in the code.

    The zasm assembler documentation is being helpful, I'm using the data segment to store the variables on RAM, and the code segment to separate the code in two origin addresses. Here's the link for it:

    https://k1.spdns.de/Develop/Projects/zasm/Documentation/

    On November 1st I plan to write another project log detailing the project results, what I learned about it, what were my expectations, and also publish the source code and instructions on GitHub.

    Here's another video showing the random tile spawing and tile shifting functionality:

  • Gameplay States

    Louis Paul10/24/2025 at 00:09 0 comments

    So for the gameplay itself I'll need to implement the rules of the 2048 game. My strategy is to create the gameplay states, such as the tile spawning state, arrow movement state, check if the movement was valid, tile shifting state, tile merging state (if possible) and game over if a new tile couldn't the spawned on the grid.

    In the tile spawning state a RNG (random number generator) is required in two moments: when selecting an available cell in the grid and determining the tile type to spawn (a 2 or 4).

    I originally planed to use the Lehmer RNG, but since the 8080 doesn't have multiply and divide opcodes, it's more annoying to implement the algorithm, so I chose the LFSR (linear-feedback shift register) method which requires only shift and XOR operations.

    For writing the 8080 code I'm using this documentation, it tells which Z80 opcodes are available on 8080:
    https://www.8bit-era.cz/z80-8080-instruction-set.html

    For debugging the code I'm using the command mame maze -debug. The problem is the disassembled code on MAME debugger window uses the 8080 syntax (like I said before, I prefer the Z80 syntax for 8080, and Intel syntax for 8086).

    It helps to learn the Z80 syntax and get familiarity with it, because in the future I could write Z80 code on another hardware, like the VIC Dual hardware.

  • Development Details

    Louis Paul10/15/2025 at 02:41 0 comments

    Now it's time to explain the development details and the code organization. Here's the memory map of the Midway 8080 hardware:

    0000-1fff: 8K ROM
    2000-23ff: 1K RAM
    2400-3fff: 7K VRAM
    4000-: RAM Mirror

    Even that the system has 8K ROM, the Amazing Maze ROMs uses 4K ROM, so I'm limited to this amount. I'm using the RAM to store the variables, such as the score digits and the array grid.

    For the VRAM (video display), I implemented text video mode with a cursor and some basic font to draw on the screen. For 256 unique tilesets it'll consume 2048 bytes (256 * 8), which will be too much, so the strategy is to use few font tilesets. If I use only 64 unique tilesets it'll consume only 512 bytes (64 * 8), which will be sufficient for special glyphs.

    I'm organizing the code by using the assembler directives like defining the data segment and code segment, and using a macro to help loading the video address to the BC register.

    For the strings I'm using a custom encoding and the strings terminate with 0xff. I have a subroutine to print it passing the string address to HL register and cursor position to BC register.

    Remember the RET opcode on the 8086 assembly which you can optionally pass an immediate value to pop the bytes after returning to calling procedure? It's very useful to implement the Pascal-style calling convention which the callee (the subroutine) is responsible to clear the arguments of the stack.

    The problem is that the RET opcode on the 8080 assembly doesn't have that, so I have to use a different calling convention. The first parameter is stored on HL register, the second on BC register, and the third on DE register.

    After all the explanation, here's the drawing of the losing screen of the 2048 game on the system (I still need to implement the gameplay):

  • Implementing the Video Mode

    Louis Paul10/08/2025 at 23:41 0 comments

    I'll describe the development progress of the 2048 game on Midway 8080 hardware. For the video mode I'm using 8-bit tile-based structure with no scrolling and no sprites. I added 8x8 basic font with the letters, numbers and special symbols. So with the 8x8 tile size and the 260x224 / 256x224 video resolution, I'll have 32x28 text resolution to draw in the screen.

    I created the 1 player mode screen and the game screen with the drawing of score and grid. I also added the input action of 1 player button and the detection of the arrows on the game screen.

    The zasm assembler I'm using supports shebang on first line (#!). Here's what I use to assemble the 8080 code (with the Z80 syntax):

    #!/usr/bin/zasm --8080 --reqcolon -l0 -o binary.rom

    After assembling the code I use this command to split the generated binary into two files:

    split -b 2048 binary.rom maze-

    Then I create a symbolic link of the file maze-aa to point to maze.h and the file maze-ab to point to maze.g, because MAME expects theses filenames to execute the ROMs.

    Showing the text video mode and screen states

    PS: I had LASIK eye surgery a week ago, so the project logs can appear less enthusiastic than usual.

  • The RetroChallenge Has Already Begun

    Louis Paul10/01/2025 at 23:24 0 comments

    Today, October 1st, is the day where the RetroChallenge officially starts, and I'll explain a bit about the current project involving the Midway 8080 hardware, the 2048 game and the development status of the 8080 assembly code.

    Looking at the arcade specifications, the Midway 8080 system is a black & white arcade hardware, has a 260x224 display, and the first game made for the hardware was Gun Fight (and the first arcade game using a microprocessor instead of being discrete logic). But the hardware is better known as the one which powers Space Invaders, there are even tutorials about how to make a emulator for it.

    However Gun Fight and Space Invaders aren't the only arcade games on this system, other games listed are Boot Hill (a sequel to Gun Fight), Sea Wolf, Laguna Racer, Clowns, Amazing Maze, and others.

    Amazing Maze one player mode (second player controlled by computer)

    Now for the explanation of the 2048 game, it's a sliding tile puzzle game created by Gabriele Cirulli in 2014, the objective of the game is to create a 2048 tile on a 4x4 grid, and the input is the arrow keys. It was hugely popular in that year, but nowadays isn't so popular anymore. Here is a image of the game in DuckDuckGo when you search for 2048 game:

    Playing the 2048 game (and failing at it)

    The Midway 8080 system uses the Intel 8080 CPU, so it'll need a 8080 assembler. I'm using the zasm assembler, and a fun fact, you can use Z80 syntax to write the code (but not the Z80 extra opcodes), I compared the Z80 syntax with the 8080 syntax and I found the Z80 syntax nicer and better to understand.

    For running the generated binary, first I assemble the code, split the binary into two 2048 bytes files, then I replace the Amazing Maze ROMs for the custom ROMs. MAME will complain about the checksums, but you can ignore it and run the new generated binary. I'm limited to 4K ROM size though, so I have to be careful to not exceed the size.

    For the moment I managed to draw the screen and read the coin input, for the next days I'll implement some sort of state machine to manage the insert a coin mode, the game itself, and maybe the attract mode.

    Testing the coin input action (it took a while to make it work)