
Welcome to DMG Programming! In this course, we will explore how to develop software for one of the most influential handheld systems ever created: the Nintendo Game Boy, also known as the DMG. Starting from the fundamentals of Assembly language, we will gradually build the skills needed to create graphics, process input, animate sprites, detect collisions, generate sound, communicate through the Link Cable, interact with peripherals, and ultimately develop complete applications and games that run on real hardware.
This course is designed to balance theory and practice. Along the way, we will not only learn how to program the DMG, but also gain insight into the principles that underpin all computer systems, from vintage handheld consoles to modern gaming devices. Whether your interest is retro programming, game development, embedded systems, or simply curiosity about how computers work at a low level, this course will provide a hands-on journey through the hardware and software of a classic machine.
By the end of the course, you will have created your own projects, experimented with real hardware, and developed a deeper understanding of the techniques that allowed developers to create memorable gaming experiences despite the limitations of the era.
Before the DMG, electronic games were often designed around a single experience. Devices such as Mattel's Auto Race, Electronic Football, dedicated handhelds, and even mechanical games were built to perform one specific task. In this lesson, we take a look at several classic electronic and mechanical toys from the 1970s and early 1980s and compare them to the DMG. We will discover that many of these devices can be viewed as specialized machines designed to play a single game, while the DMG is a programmable machine capable of becoming any of them through software.
Along the way, we will compare dedicated devices such as the original Donkey Kong Game & Watch with their DMG counterparts and explore how a single piece of hardware can reproduce the behavior of many different machines. By the end of this lesson, you will understand why the DMG represents a major shift in design philosophy and why programmable systems eventually replaced most dedicated electronic toys.
In this lesson we take apart a real DMG and examine the hardware that powers the system. We will identify the major components, explore how the console is physically assembled, and discover that the DMG is essentially divided into two main subsystems: a motherboard containing the CPU, memory, and supporting electronics, and a separate board containing the LCD screen, speaker, controls, and user interface components. By the end of this lesson, you will have a better understanding of how the hardware is organized and how the different parts work together to create the complete system.
Viewed from a high level, the DMG can be thought of as a computer connected to a terminal. The motherboard performs the computation, while the display board handles presentation, sound output, and user input. This separation helps illustrate a common design pattern found throughout computing history, from early terminals connected to mainframes to modern embedded systems and handheld devices.
Wait a minute... wasn't the DMG the first handheld gaming system with interchangeable cartridges? Not quite. More than a decade earlier, Mattel released the MicroVision, a pioneering handheld console that introduced the concept of swappable game cartridges. In this lesson, we take a brief look at this fascinating piece of gaming history and compare its architecture with that of the DMG. By the end of this lesson, you will understand how the two systems approached the same problem in very different ways and why the DMG's design ultimately proved far more influential.
The comparison highlights an important lesson in engineering: there is often more than one way to solve a problem. While the MicroVision and the DMG both allowed players to swap games, they distributed the hardware responsibilities differently, leading to very different tradeoffs in cost, flexibility, reliability, and long-term success.
In this lesson we set up our development environment in order to get ready to develop for the DMG. By the end of this lesson, you will have your RGBDS ToolChain and Emulator all set.
In this lesson we set up our development environment in order to get ready to develop for the DMG. By the end of this lesson, you will have your RGBDS ToolChain and Emulator all set.
In this lesson we set up and configure VSCode as our code editor. By the end of this lesson, you will have everything ready to create your first program in ASM for the DMG
In this lesson we introduce and explain the philosophy and mindset needed to get a firm grasp on how to program in Assembly Language.
In this lesson we introduce and explain the concepts behind different number system (decimal, binary and hexadecimal).
If you are already familiar with decimal, binary and hexadecimal number systems, feel free to skip the next three lessons.
In this lesson we review the concepts behind the number system that we are mostly used to: the decimal number system. By the end of this lesson, you will be ready to understand other number systems.
In this lesson we explore the binary number system, the language spoken by computers. By the end of this lesson, you will understand how binary numbers work and how to convert between binary and decimal.
In this lesson we learn about the hexadecimal system and why it is so commonly used in computer science. By the end of this lesson, you will understand how the hexadecimal number system works and how to convert between decimal, hexadecimal and binary.
In this lesson we discuss how to represent negative numbers using the binary system. We explore some ideas and which ones might work.
In this lesson we introduce and explain the concepts behind Two's Complement, which is the de-facto standard to represent negative numbers. By the end of this lesson, you will understand how it works and how it is used on the DMG.
In this lesson we introduce and explain the concepts behind Registers, the "variables" that are built into the CPU. By the end of this lesson, you will understand how it works and how it is used on the DMG.
In this lesson we introduce and explain how to load and read variables from the Registers using Assembly Language.
It is time to get out hands dirty! In this lesson we continue building upon our knowledge about registers and we create our first Assembly program. We will load values into the registers and confirm that everything is working.
In this lesson we introduce and explain the concepts behind the startup logo which appears every time you power on your DMG. By the end of this lesson, you will understand how it works and how it was used as an early copy-protection mechanism and to check if the cartridge was working well and was well connected.
In this lesson we introduce and explain how to load and store values into the RAM Memory of the DMG.
In this lesson we implement loading and storing values into RAM in Assembly language and test it on the DMG platform.
In this lesson we introduce and explain the concept of constants, which help improve the readability and maintainability of our Assembly programs. By the end of this lesson, you will be able to replace hardcoded values with meaningful names.
In this lesson we introduce arithmetic operations on the DMG, starting with addition. By the end of this lesson, you will understand how the CPU performs addition and how the result affects the processor flags.
In this lesson we dive further into addition on the DMG and explain what happens when we get an overflow.
In this lesson we introduce and explain the concepts behind the rest of the arithmetic operations that the DMG is capable of performing : subtraction, incrementing, decrementing. By the end of this lesson, you will understand how arithmetic operations are performed on the DMG. Notice that there is no such thing as multiplication (or division)
In this lesson we put the Jump instruction into practice by creating a simple Assembly program and observing how program execution changes. By the end of this lesson, you will have firsthand experience controlling program flow.
In this lesson we implement "Jump" in Assembly language and test it on the DMG emulator.
In this lesson we introduce and explain the concepts behind the "Relative Jump", an easier and faster version of the normal "Jump". We will also discuss its limitation and use-cases.
In this lesson we introduce and explain the concepts behind logical operations, starting with AND and OR. These instructions allow us to manipulate individual bits inside a value, making them extremely useful when working with hardware registers and flags. By the end of this lesson, you will understand how AND and OR work and how they are used in Assembly language on the DMG.
In this lesson we introduce and explain the XOR (Exclusive OR) logical operation and explore its unique properties. Unlike AND and OR, XOR produces a result only when the input bits are different, making it useful for tasks such as toggling bits, comparing values, and simple data manipulation techniques. By the end of this lesson, you will understand how XOR works and how it is used in Assembly language on the DMG.
In this lesson we introduce and explain the CP (Compare) instruction, which allows us to compare two values without modifying them. We will see how the CPU performs an internal subtraction and updates its flags to indicate whether values are equal, greater, or smaller. By the end of this lesson, you will understand how comparisons work on the DMG and how they are used to make decisions in Assembly programs.
In this lesson we introduce and explain the concepts behind bit shifting, one of the most fundamental operations in low-level programming. We will see how bits can be moved left or right within a value and explore the effects this has on the data being stored. By the end of this lesson, you will understand how bit shifting works on the DMG and how it can be used for efficient arithmetic operations and data manipulation.
In this lesson we explore how multiplication can be performed on the DMG even though the CPU does not provide a dedicated multiplication instruction. By using bit-shifting techniques, we can efficiently multiply values by powers of two while gaining a deeper understanding of how arithmetic operations work at the hardware level. By the end of this lesson, you will understand how bit shifting can be used to perform multiplication and why this technique is commonly used in low-level programming.
In this lesson we introduce and explain the 16-bit registers available on the DMG CPU. While most of the registers we have used so far store 8-bit values, certain operations require larger values and memory addresses, making 16-bit registers essential. By the end of this lesson, you will understand how 16-bit registers work, how they are formed from pairs of 8-bit registers, and how they are used in Assembly language on the DMG.
In this lesson we introduce and explain the concepts behind function calls, one of the most important techniques for organizing and reusing code. We will see how the CPU can temporarily jump to another section of code, execute a sequence of instructions, and then return to where it left off. By the end of this lesson, you will understand how function calls work on the DMG and how they help create cleaner and more maintainable Assembly programs.
In this lesson we put our knowledge of registers, memory, loops, and arithmetic operations into practice by creating a program that loads a sequence of numbers into RAM. We will build the solution step by step and verify that the values are stored correctly in memory. By the end of this lesson, you will understand how multiple Assembly concepts work together to solve a practical programming problem on the DMG.
In this lesson we introduce and explain the concepts behind the Stack, a special area of memory used by the CPU to temporarily store information. We will explore how values can be pushed onto and popped off the stack, and why this mechanism is essential for function calls and many other programming techniques. By the end of this lesson, you will understand how the stack works on the DMG and how it is used to manage program execution.
In this lesson we introduce and explain the concepts behind macros, a powerful feature that allows us to define reusable blocks of Assembly code. Macros can help reduce repetition, improve readability, and make programs easier to maintain by generating code automatically during assembly. By the end of this lesson, you will understand how macros work and how to use them effectively in your DMG Assembly projects.
In this lesson we put macros into practice by creating and using our own reusable Assembly code. We will see how macros can simplify repetitive tasks, make programs easier to read, and reduce the amount of code we need to write. By the end of this lesson, you will understand how to create and use macros effectively in your DMG projects.
In this lesson we introduce and explain the graphics system of the DMG. We will explore how the Game Boy generates images on the screen, the limitations imposed by the hardware, and the techniques developers used to create visually appealing games despite these constraints. By the end of this lesson, you will understand the fundamental concepts behind graphics programming on the DMG.
In this lesson we continue our exploration of the graphics system of the DMG. We will build upon the concepts introduced previously and take a closer look at how graphics data is organized and displayed by the hardware. By the end of this lesson, you will have a solid understanding of the foundations of graphics programming on the DMG.
In this lesson we introduce and explain the concept of a tile, the fundamental building block used to create graphics on the DMG. We will explore how images are broken down into small 8×8 pixel blocks and how these tiles are stored in memory. By the end of this lesson, you will understand how tiles work and why tile-based graphics were such an efficient solution for the hardware limitations of the DMG.
In this lesson we put our knowledge of tiles into practice by creating and displaying our first custom tile on the DMG. We will follow the complete process, from defining the tile data in memory to rendering it on the screen. By the end of this lesson, you will understand how graphics data is represented and displayed by the DMG hardware.
In this lesson we debug our first tile drawing demo and investigate why the tile appears corrupted on screen. We will identify common graphics mistakes, such as writing to VRAM outside of VBLANK and using an incorrect palette configuration. By the end of this lesson, you will understand how to diagnose basic graphics issues on the DMG and why timing matters when working with video memory.
In this lesson we introduce and explain how to wait for VBLANK, the period when the DMG is drawing offscreen and it is safe to update video memory. We will implement a simple busy-waiting algorithm that checks the video status before continuing execution. By the end of this lesson, you will understand why VBLANK is important and how to synchronize your graphics code with the DMG display hardware.
In this lesson we analyze the limitations of our busy-waiting VBLANK algorithm. While it correctly waits until it is safe to update video memory, it also keeps the CPU active while doing nothing useful, which can waste power and drain the battery faster. By the end of this lesson, you will understand why busy waiting is not always the best solution and why interrupts provide a better way to react to VBLANK on the DMG.
In this lesson we introduce and explain the VBLANK Interrupt, a hardware mechanism that automatically notifies the CPU when the display has finished drawing a frame. Unlike busy waiting, interrupts allow the CPU to remain idle until needed, resulting in more efficient programs and lower power consumption. By the end of this lesson, you will understand how the VBLANK Interrupt works and why it is the preferred way to synchronize graphics updates on the DMG.
In this lesson we put the VBLANK Interrupt into practice by modifying our graphics program to react automatically when VBLANK occurs. We will replace our busy-waiting approach with an interrupt-driven solution and observe how the program behaves. By the end of this lesson, you will understand how to use the VBLANK Interrupt in your own DMG programs and why it is a more efficient solution for graphics updates.
In this lesson we introduce and explain how to temporarily turn off the LCD screen on the DMG. Doing so allows us to perform large transfers to VRAM without having to worry about VBLANK timing restrictions. We will discuss when this technique is useful, its limitations, and the precautions that must be taken when disabling and re-enabling the display. By the end of this lesson, you will understand how and when to safely turn off the LCD screen while developing graphics-intensive programs for the DMG.
In this lesson we put the LCD shutdown process into practice by implementing it safely in Assembly language. We will wait for the proper moment, disable the LCD screen, perform larger VRAM operations without timing conflicts, and then re-enable the display. By the end of this lesson, you will understand how to safely turn off the LCD screen on the DMG and use this technique in your own graphics programs.
In this lesson we introduce and explain how to clean video memory before displaying graphics on the DMG. With the LCD screen turned off, we can safely reset VRAM by filling it with zeroes, preventing old or uninitialized data from appearing as visual glitches when the screen is turned back on. By the end of this lesson, you will understand why cleaning video memory is important and how it helps create a clean and predictable graphics setup.
In this lesson we complete our graphics initialization process by turning the LCD screen back on after cleaning VRAM and loading our graphics data. We will verify that everything has been set up correctly and observe the results on screen. By the end of this lesson, you will understand how to safely re-enable the LCD screen and display graphics without visual glitches on the DMG.
In this lesson we explore various sources of graphics assets that can be used in DMG projects. We will look at sprites, tilesets, icons, and other artwork created by the retro gaming community, while discussing the characteristics that make graphics suitable for the DMG hardware. By the end of this lesson, you will know where to find graphics assets and how to evaluate whether they are a good fit for your projects.
In this lesson we introduce and explain RGBGFX, a tool that allows us to prepare graphics for use on the DMG. We will learn how to take artwork and transform it into a format that can be understood by the hardware. By the end of this lesson, you will understand the role of RGBGFX in the development workflow and how it helps bridge the gap between modern graphics and the DMG graphics system.
In this lesson we introduce and explain how graphical assets are stored inside a DMG cartridge. Since the DMG does not provide a file system, graphics cannot be loaded from individual files at runtime and must instead become part of the ROM itself. We will learn how to include graphical data in our project and make it available to our program. By the end of this lesson, you will understand how assets are stored in a DMG ROM and how your program can access them.
In this lesson we put our graphical assets to use by loading tiles and tilemaps from ROM into VRAM. We will transfer the graphics data needed by the display hardware and prepare the screen to render our first complete background. By the end of this lesson, you will understand how graphical assets move from ROM to VRAM and how the DMG uses tiles and tilemaps to construct a scene.
In this lesson we take a photograph and prepare it for use on the DMG using GIMP. We will explore the challenges of adapting a modern image to the DMG's limited resolution and four-shade palette, making adjustments until it is suitable for the hardware. By the end of this lesson, you will understand the process of converting real-world images into graphics that can be displayed on the DMG.
In this lesson we explore an alternative way to prepare an image for the DMG by using a custom Python script. While Python is not required for the course, this approach shows how we can automate parts of the conversion process and build our own tools when needed. By the end of this lesson, you will understand how scripting can support your DMG development workflow and give you more control over how graphical assets are prepared.
In this lesson we introduce the challenge of displaying text on the DMG. While printing "Hello World" may seem like a simple task, it requires combining many of the graphics concepts we have learned so far, including tiles, tilemaps, VRAM, and memory management. By the end of this lesson, you will understand the overall approach we will take to display text on the screen and why this seemingly simple task is more complex than it first appears on the DMG.
In this lesson we explore how screen coordinates relate to locations in the DMG's tilemap memory. Given a position on the screen, we will learn how to calculate the corresponding memory address where a tile must be written. By the end of this lesson, you will understand how to translate screen coordinates into tilemap positions and how this knowledge can be used to place text and graphics anywhere on the screen.
In this lesson we take a closer look at the formula used to convert screen coordinates into tilemap memory addresses. While the approach appears straightforward, we soon discover a limitation of the DMG CPU: part of the calculation requires multiplying by 32, a value that can easily exceed the capacity of an 8-bit register. By the end of this lesson, you will understand the source of this problem and why we need a different approach to perform the calculation correctly on the DMG.
In this lesson we implement sla16, a custom macro that mimics the behavior of the original SLA instruction but works on 16-bit register pairs. This allows us to shift larger values safely when performing calculations that do not fit inside a single 8-bit register. By the end of this lesson, you will understand how to extend existing Assembly operations using macros and how this helps solve practical limitations of the DMG CPU.
In this lesson we implement the full tile address calculation in Assembly language. Using the formulas we analyzed earlier and our custom sla16 macro, we will convert screen coordinates into the correct tilemap memory position. By the end of this lesson, you will understand how to perform this calculation on the DMG and how to place tiles at specific locations on the screen.
In this lesson we bring together everything we have learned so far to finally display "Hello World" on the DMG screen. We will use our tile graphics, tilemap memory calculations, and Assembly routines to place characters at the correct locations and render the message. By the end of this lesson, you will understand how text is displayed on the DMG and have created your first complete text-rendering program.
In this lesson we introduce and explain how the DMG detects player input. We will explore the hardware registers responsible for reading the buttons and examine a simple template that we will build upon throughout this section. By the end of this lesson, you will understand the fundamentals of input detection on the DMG and be ready to start reading button presses.
In this lesson we implement input detection by polling the DMG input registers. We will read the state of the directional pad and buttons, combine the results into a single byte, and store them for later use by our program. By the end of this lesson, you will understand how input polling works and how to retrieve the current state of the DMG controls.
In this lesson we take our first step toward interactive programs by detecting when the UP key is pressed. Using the template introduced earlier, we will read the input state and update the display accordingly. By the end of this lesson, you will understand how to test for a specific button press and react to user input on the DMG.
In this lesson we extend our input detection system to support all of the DMG buttons. Building upon the code created previously, we will add checks for each key and update the display to reflect their current state. By the end of this lesson, you will understand how to handle multiple inputs and create a complete button detection system.
In this lesson we improve our input handling code by replacing repetitive button detection logic with a reusable macro. This approach reduces duplication, improves readability, and makes the program easier to maintain. By the end of this lesson, you will understand how macros can simplify Assembly programs and help manage more complex input systems on the DMG.
In this lesson we introduce and explain OAM Objects, more commonly known as sprites. We will explore how sprites differ from background tiles, how they are configured and displayed on the DMG, and the hardware limitations that developers must work within. By the end of this lesson, you will understand how sprites are represented in memory and how they are used to create moving objects and characters on the screen.
In this lesson we draw our first sprite on the DMG and learn how to configure an OAM object in Assembly language. As we test our program, we encounter some unexpected visual glitches caused by uninitialized OAM memory, leading to the appearance of unwanted sprites on the screen. By the end of this lesson, you will understand how to display a sprite, recognize common OAM-related issues, and appreciate the importance of properly initializing sprite memory
In this lesson we clean and initialize OAMRAM before creating any sprites. By clearing the sprite memory, we eliminate unwanted objects and visual glitches caused by leftover data. By the end of this lesson, you will understand why OAM initialization is important and how to ensure that only the sprites you explicitly create appear on the screen.
In this lesson we verify that our input system is working correctly before attempting to move our sprite. Using the input handling code developed earlier, we will check whether the LEFT key is being pressed and use a simple macro to confirm that the detection logic behaves as expected. By the end of this lesson, you will understand the value of testing individual systems in isolation and have confidence that our input code is ready for sprite movement.
In this lesson we thoroughly test our input system by verifying that all directional keys are detected correctly. Using simple debug messages, we will confirm that each button press is recognized before moving on to sprite movement. By the end of this lesson, you will have validated your input handling code and gained confidence that it is working reliably on the DMG.
In this lesson we introduce XDelta and YDelta, two variables that will determine how much our sprite should move horizontally and vertically. Based on the keys currently being pressed, we will calculate the appropriate offsets and store them in memory. If no directional keys are pressed, both values will remain zero. By the end of this lesson, you will understand how to separate input detection from movement logic and prepare the data needed to move a sprite on the DMG.
In this lesson we bring together our input handling and movement systems to finally move a sprite using the D-PAD. Using the XDelta and YDelta values calculated previously, we will update the sprite's position and see it respond to player input in real time. By the end of this lesson, you will understand how input, movement logic, and sprite positioning work together to create interactive programs on the DMG.
In this lesson we add a simple but important visual improvement by making our sprite face the direction in which it is moving. We will use the sprite attribute flags to flip the sprite horizontally and update its appearance based on player input. By the end of this lesson, you will understand how sprite flipping works on the DMG and how a small change can make character movement feel much more natural and responsive
In this lesson we discuss how to keep a sprite within the visible boundaries of the DMG screen. While our current implementation allows the sprite to move freely, this can result in it partially or completely disappearing off-screen. We will explore the logic required to detect screen boundaries and prevent invalid movement before implementing it in a future lesson. By the end of this lesson, you will understand the concepts behind screen constraints and how they can improve the behavior of your games and applications.
In this lesson we implement horizontal screen boundaries for our moving sprite. We will check the sprite's X position before applying movement, preventing it from moving too far left or too far right and disappearing off-screen. By the end of this lesson, you will understand how to enforce horizontal limits and keep sprites within the visible area of the DMG screen.
In this lesson we continue our work on screen boundaries by exploring vertical movement constraints. We will discuss how to prevent a sprite from leaving the visible area of the DMG screen and implement a boundary check for the top edge. By the end of this lesson, you will understand the principles behind vertical screen constraints and how they can be applied to sprite movement.
In this lesson we complete our vertical boundary system by implementing the lower screen limit. Building upon the concepts introduced previously, we will prevent the sprite from moving beyond the bottom edge of the DMG display and verify that the solution works correctly. By the end of this lesson, you will understand how to fully constrain vertical movement and keep sprites within the visible screen area.
In this lesson we introduce and explain the RSSET and RSRESET macros, two useful tools for organizing data structures and memory layouts in Assembly language. We will see how these macros can automatically calculate offsets and simplify the definition of related variables. By the end of this lesson, you will understand how RSSET and RSRESET work and how they can help create cleaner and more maintainable DMG programs.
In this lesson we analyze the shortcomings of our current input handling approach and propose a more flexible solution. Instead of simply detecting whether a button is pressed, we will separate input into three distinct events: button pressed for the first time, button currently held down, and button released. By the end of this lesson, you will understand why these distinctions are important and how they can be used to create more responsive and polished DMG applications and games.
In this lesson we design a more advanced input handling system capable of distinguishing between different types of button interactions. Using a flowchart-based approach, we will define the logic required to detect when a button is pressed for the first time, held down, or released. By the end of this lesson, you will understand the structure of the improved input system and how the various input events will be generated from the current and previous button states.
In this lesson we begin setting up the foundation for our improved input system. Using the RSSET and RSRESET macros, we will organize the memory structures needed to track current and previous button states, while also creating the initial framework for our input processing logic. By the end of this lesson, you will understand how the new input system is organized and how its different components fit together.
In this lesson we continue building the foundation for our improved input system. We will expand the memory structures and complete the initial implementation framework that will allow us to detect button presses, held buttons, and button releases. By the end of this lesson, you will have a complete input system skeleton ready for the implementation of the individual input events.
n this lesson we create ld_mem, a utility macro designed to simplify memory assignments in Assembly language. Internally, the macro handles the temporary use of the Accumulator register and preserves its original value by saving and restoring it automatically. This allows us to copy values between registers and memory locations without worrying about side effects elsewhere in our program. By the end of this lesson, you will understand how the ld_mem macro works and how custom macros can make Assembly code cleaner, safer, and easier to maintain.
In this lesson we implement our improved input system in Assembly language. Using the memory structure and flow designed in the previous lessons, we will compare the current and previous input states to detect when a button is newly pressed, held down, or released. By the end of this lesson, you will understand how to generate different input events on the DMG and use them as the foundation for more responsive controls.
In this lesson we test our improved input system and verify that it correctly detects different button events. We will check whether the DMG can distinguish between a button being newly pressed, held down, and released.
In this lesson we continue testing our improved input system and verify that it correctly detects different button events. We will check whether the DMG can distinguish between a button being newly pressed, held down, and released. By the end of this lesson, you will have confirmed that the new input system works as expected and is ready to be used in more advanced interactive programs.
In this lesson we increase the speed of our sprite by adjusting the movement offsets applied each frame. Rather than moving a single pixel at a time, we will use larger XDelta and YDelta values to make movement faster and more responsive. By the end of this lesson, you will understand how movement speed is controlled on the DMG and how small changes to movement calculations can significantly affect the feel of your program.
In this lesson we explore how to achieve smoother and slower sprite movement by introducing fractional positions. Using 16-bit registers in an 8.8 fixed-point format, we will store both the whole and fractional portions of a position, allowing movement increments smaller than a single pixel. By the end of this lesson, you will understand how fixed-point arithmetic works and how it can be used on the DMG to create smoother and more precise movement.
In this lesson we introduce and explain the fundamental concepts behind collision detection on the DMG. Rather than focusing on highly optimized techniques, we will start with a simple and easy-to-understand approach that can be implemented quickly and reused in many different projects. We will examine how objects can be represented by rectangular areas and how overlapping regions can be used to determine whether a collision has occurred. By the end of this lesson, you will understand the basic principles of collision detection and be ready to implement your first collision system on the DMG.
In this lesson we set up the project we will use to implement collision detection. Instead of starting from scratch, we will use a template that already includes sprite movement, the improved input system, and a predefined rectangular area on the screen. Our goal will be to prevent the sprite from entering that rectangle. By the end of this lesson, you will understand the structure of the collision demo and the problem we are trying to solve.
In this lesson we begin implementing collision detection one boundary at a time. We will focus only on the left side of the rectangular area and test whether the sprite has crossed that boundary. Instead of blocking movement immediately, we will change the sprite's color to confirm that our collision test is working. By the end of this lesson, you will understand how to isolate and test a single collision condition before combining it with the others.
In this lesson we continue building our collision detection system by testing the right side of the rectangular area. We will determine whether the sprite has crossed the right boundary and use a color change to verify that our collision test is functioning correctly. By the end of this lesson, you will understand how to implement and validate another collision condition before combining it with the others.
In this lesson we continue building our collision detection system by testing the upper side of the rectangular area. We will determine whether the sprite has crossed the top boundary and use a color change to verify that our collision test is functioning correctly. By the end of this lesson, you will understand how to implement and validate another collision condition before combining it with the others.
In this lesson we complete our collision detection system by testing the lower side of the rectangular area. Unlike the previous lessons, we will go beyond simply detecting a collision and implement a basic collision response system. By storing the sprite's previous position and restoring it whenever a collision occurs, we can prevent the sprite from entering the restricted area. By the end of this lesson, you will understand how collision detection can be combined with collision response to create solid boundaries on the DMG.
In this lesson we revisit our collision system to fix an issue introduced in the previous implementation. Due to a mistake in the collision response logic, the sprite exhibits an unintended "bouncing" behavior when colliding with the obstacle. We will analyze the cause of the problem, correct the implementation, and verify that the sprite now behaves as expected. By the end of this lesson, you will understand how small logic errors can affect collision systems and how to troubleshoot and fix them effectively.
In this lesson we extend our collision system by exploring how to determine which side of an object was hit during a collision. Up to this point, our code has only answered the question "Did a collision happen?" Now we will investigate how additional logic can be used to identify whether the collision occurred on the top, bottom, left, or right side of an object. By the end of this lesson, you will understand why collision side detection is important and how it can be used to create more advanced gameplay mechanics on the DMG.
In this lesson we implement the logic required to determine whether a collision occurred on the left side of an object. Building upon our existing collision detection system, we will compare object positions and movement direction to identify this specific collision case. By the end of this lesson, you will understand how left-side collisions can be detected and how this information can be used to drive gameplay behavior.
In this lesson we implement the logic required to determine whether a collision occurred on the right side of an object. Building upon our existing collision detection system, we will compare object positions and movement direction to identify this specific collision case. By the end of this lesson, you will understand how right-side collisions can be detected and how this information can be used to drive gameplay behavior.
In this lesson we implement the logic required to determine whether a collision occurred on the upper or lower side of an object. Building upon our existing collision detection system, we will analyze object positions and movement direction to distinguish between these two cases. By the end of this lesson, you will understand how vertical collision sides can be identified and how they can be used to create different gameplay outcomes depending on the direction of impact.
In this lesson we redesign our collision system so that multiple objects can handle collisions independently. Each collider will not only define its rectangular boundaries, but also reference a specific piece of code that should be executed when a collision occurs. We will establish a mechanism for passing collision information, such as the objects involved and the side of the collision, to these event handlers using shared variables. By the end of this lesson, you will understand how to decouple collision detection from collision response and build a more flexible and reusable collision system on the DMG.
In this lesson we demonstrate how different colliders can trigger different behaviors when a collision occurs. Using the event-based system introduced previously, we will assign separate event handlers to different collision objects and observe how each one responds in its own way. By the end of this lesson, you will understand how collision events can make your DMG programs more flexible, reusable, and easier to expand.
In this lesson we explore a practical limitation of the DMG hardware when working with large numbers of sprites. By attempting to update all 40 sprites every frame, we will discover that there is not enough time during VBLANK to manually transfer all of the required sprite data to OAM memory. We will examine the consequences of this limitation and discuss why a more efficient solution is needed. By the end of this lesson, you will understand the motivation behind DMA (Direct Memory Access) and why it became an essential technique for sprite management on the DMG.
In this lesson we explore how DMA (Direct Memory Access) works on the DMG and why it provides a much faster way to update sprite data. We will examine how the hardware can automatically transfer OAM data without requiring the CPU to manually copy each byte, dramatically reducing the time needed to update all 40 sprites. We will also discuss the limitations of DMA, including the temporary restrictions placed on memory access while a transfer is in progress. By the end of this lesson, you will understand how DMA operates, why it improves performance, and what precautions must be taken when using it on the DMG.
In this lesson we implement the DMA copy routine in Assembly language. Because ROM access is restricted while DMA is running, we will copy the DMA routine into HRAM, execute it from there, wait the required 160 cycles for the transfer to complete, and then return safely back to ROM. By the end of this lesson, you will understand how to perform an OAM DMA transfer correctly and why HRAM is essential for this process on the DMG.
In this optional lesson we explore an advanced DMA technique for displaying more than 40 sprites on the DMG. By using a line count interrupt and triggering a second DMA transfer after part of the screen has already been drawn, we can swap the OAM data during the frame and create the illusion of having more sprites available. By the end of this lesson, you will understand the idea behind this DMA hack, its limitations, and why timing is critical when attempting more advanced hardware tricks on the DMG.
DMG Programming: Learn Assembly and Game Development on the Nintendo Game Boy
The Nintendo Game Boy, also known as the DMG, is one of the most influential handheld systems ever created. Despite having only a fraction of the processing power of modern devices, it remains one of the best platforms for learning how computers, games, and hardware truly work.
In this course, you will learn how to program the Game Boy from the ground up using Assembly language. Starting with the fundamentals of the CPU and memory architecture, we will gradually build the skills needed to create graphics, process player input, animate sprites, detect collisions, generate sound, communicate through the Link Cable, interact with external peripherals, and ultimately develop complete applications and games that run on real hardware.
This course is designed to be highly practical. Rather than focusing exclusively on theory, we will build real projects step by step, including a complete Flappy Bird-style game. Along the way, we will explore many aspects of the DMG hardware:
Assembly Language Programming
Graphics and Tile-Based Rendering
Sprites and OAM Management
Input Processing
Collision Detection
DMA Transfers
Random Number Generation
Audio Programming
Timers and Interrupts
Serial Communication
The Game Boy Printer
The Game Boy Camera
MIDI Integration
Real Hardware Testing and Debugging
You will also learn how to work with modern development tools such as RGBDS and RGBGFX, convert your own images for use on the DMG, generate music data from MIDI files, and create software that runs both in emulators and on original hardware.
Unlike many introductory courses, this course does not stop when the program compiles. We will test our projects on real Game Boys, examine hardware-specific bugs, and learn why real hardware validation remains important even today.
Along the way, we will also take a broader look at the history of handheld computing and gaming. We will compare the DMG with earlier systems such as the MicroVision, examine classic electronic toys from the 1970s and 1980s, disassemble a real Game Boy to understand its internal architecture, and explore the idea that a programmable machine can become many different machines through software alone.
By the end of the course, you will not only know how to create software for the Game Boy—you will understand many of the same fundamental concepts that power modern computers, game consoles, smartphones, and embedded systems.
Whether your interest is retro programming, game development, computer architecture, embedded systems, or simply understanding how computers work beneath the surface, this course will provide a hands-on journey through one of the most elegant and approachable computing platforms ever created.
Because at the end of the day, a modern handheld and a Game Boy have more in common than you might think.
One renders millions of textured triangles per second.
The other draws tiles.
Both are computers executing instructions, moving data through memory, and transforming that data into experiences.
The scale has changed.
The principles have not.
What you'll build
A complete Flappy Bird-style game
Sprite-based demos
Collision systems
Audio playback systems
MIDI-controlled music experiments
Serial communication demos
Multiplayer Link Cable applications
Game Boy Printer projects
Real hardware demonstrations
Who this course is for
Programmers who want to learn low-level programming
Game developers curious about retro hardware
Computer science students interested in computer architecture
Embedded systems enthusiasts
Retro-computing hobbyists
Anyone who has ever wondered how games worked before modern engines
No prior Assembly language experience is required. The course starts from the basics and gradually builds toward complete applications and games.
Welcome to the DMG - The Universal Toy Machine