RubyConf TH 2022

Megaruby - mruby/c on Sega Mega Drive

A talk from RubyConfTH, held in Bangkok, Thailand on December 9-10, 2022.

Find out more and register for updates for our 2023 conference at https://rubyconfth.com/

RubyConfTH 2022 videos are presented by Cloud 66. https://cloud66.com

RubyConf TH 2022

00:00:00.120 foreign
00:00:16.160 Thanks for the introduction and thanks everyone for being here. I also want to express my gratitude to the organizers for giving me this opportunity to talk about the Dreamcast in a single-track conference where you have no alternative to attend something more practical or useful. I absolutely appreciate this.
00:00:22.560 Right now, on this bench, I've set up my Mega Drive, and it's connected. The screen output you see right now comes from the Mega Drive unit. I cannot lift it at the moment, so I have my special cartridge instead. This is what a Mega Drive looks like, and this special cartridge allows me to boot images from an SD card. I've got something similar in here as well.
00:01:17.280 This is the screen output from the special cartridge that I've got, and it displays a list of ROM images I can select. Sorry, because I have no screen, a lot of times I'll be facing the screen like this. This lets me select my presentation image, so let's get started on this.
00:01:32.220 Oh no, thank you. This is awkward; I'm wearing the same design. And thanks again to the organizers. So here we go! This is my presentation application. I wrote this for the Mega Drive using Ruby and C.
00:01:41.900 I've called it Mega Present. I originally wrote this for Ruby Kaji in September, and since then, I've added a small number of updates and new content. Now I call it Mega Present Dash. Let's go ahead and press start. Here’s a table of contents: I’ll briefly introduce myself, talk about the Mega Drive, discuss Ruby andRuby/C, present why Ruby on Mega Drive is a good idea, explain something called SGDK, and finally, show some sample code. I’ll end with a demo game, or actually a tiny demo game and a slightly bigger demo game.
00:02:18.120 So, this is me—a pixel art version of myself. I'm Yoji, and I live in Adelaide, Australia. I'm originally from Tokyo, Japan. You can contact me through these social channels, but the bottom one is a newly created account where I haven't done much yet. I think that might be where I'll go if anything happens with Twitter.
00:02:27.660 Now, let's get started with this question: What is the Mega Drive? As mentioned by Matt, some of you here may not know what the Mega Drive is. The Mega Drive was released in 1988 by Sega and is also known as the Sega Genesis in some parts of the world. It featured a Motorola 68,000 CPU, clocked at approximately 7.6 megahertz—not gigahertz, but megahertz. The main RAM was 64 kilobytes—not megabytes or gigabytes—but 64 kilobytes, and the video RAM was also 64 kilobytes. The Motorola 68k is known as a 16-bit processor, although it has some 32-bit features.
00:03:06.180 The Mega Drive proudly indicated its 16-bit capabilities in its design and was very popular back in the day. Over 30 million units were sold worldwide, and it was actually more popular outside of Japan than it was in Japan. Now, let’s talk about MRuby. MRuby is another implementation of Ruby, and throughout the day, we've heard about various implementations of Ruby.
00:03:39.360 By default, if you are not really paying attention to which implementation you’re using, you're probably using CRuby. Another popular implementation is JRuby, which you’ll hear more about at this conference. MRuby is a bit different from many others because it focuses on embedded environments. It integrates very well with C.
00:04:12.660 You might wonder how MRuby differs from C-based native extensions in Ruby. You can call C functions from Ruby, but with MRuby, you can write Ruby code that's callable from C, which is actually quite difficult to achieve with CRuby. Some features you expect to find in CRuby, such as 'require' and 'eval', do not exist in MRuby, mainly because they are complex to implement.
00:04:54.540 Additionally, there is no gem to add features at execution time; however, there is something called mrb gem that allows the addition of features during compile time when you build your program. These differences between MRuby and CRuby are significant, and with MRuby, typical target environments operate on hundreds of kilobytes of RAM. There's also MRuby/C, often known as mrbc, which I’ve used for this project.
00:05:56.220 MRuby/C is a VM-only project that provides a more compact VM, originating from the Kyushu Institute of Technology and the MIT Open Innovation Center. It focuses on being small, thus, class libraries in MRuby are more limited, and there isn’t a system like mrb gem for mrbc, meaning you would need to add features directly into your source code if you need them.
00:06:40.380 Now, you might wonder why develop for the Mega Drive in 2022. It’s actually not a bad idea. There are numerous good open-source development kits, and I specifically use one called SGDK. There are plenty of second-hand units sold, which are still in good condition. Unlike the Dreamcast, which has limited compatible hardware, there are third-party vendors selling compatible implementations of the Mega Drive.
00:07:50.520 So, if a Mega Drive breaks down, the hardware needed to run your code is abundant. Additionally, there are good emulators available that are extremely handy for development. There are also many active projects and indie studios creating commercial Mega Drive games even today.
00:08:30.240 You can even find projects on Kickstarter related to the Mega Drive. Now, would it make sense to use MRuby on Mega Drive? Well, you get to write your main game logic in Ruby, which I think is a good enough reason. You do need to write the beginning entry point in C and have to handle a lot of platform library calls in C, but the core logic can be written in Ruby.
00:09:10.800 For instance, in my presentation, the core presentation logic is in Ruby. Let’s talk about SGDK, which is a development kit for the Sega Genesis/Mega Drive. It provides a C API so you don’t have to write in assembly, and features functional memory management, such as malloc and free, which is often not available in small embedded environments.
00:09:54.840 SGDK also manages graphics elements like tiles, sprites, and palettes effectively. The default font you see on the screen right now comes from SGDK's default font. The Mega Drive features a Z80 processor for sound control, and SGDK can communicate with that, providing even more capabilities.
00:10:25.440 Because I’m using SGDK and MRuby, I’ve modified the build system to create an executable that suits my application's requirements. SGDK and the build system expect a main entry point, producing an executable, while MRuby defaults to producing a library. There are sample programs in MRuby, but the main entry points are only found in the samples directory.
00:11:01.740 I checked out the entire mrb C repository and added my own main function as the entry point, modifying it to build a single executable. Along the way, I aggressively cut out components that caused build issues, resulting in some missing features compared to the complete MRuby feature set.
00:11:45.360 Now, let’s discuss Mega Drive graphics. It’s quite different from modern computers. The Mega Drive comes with what’s called a video display processor (VDP) that runs at about 13 megahertz and can operate in NTSC or PAL formats.
00:12:35.240 In case you don't know, NTSC is common in the US and Japan, running with a higher refresh rate but lower resolution, while PAL, popular in Europe, has a higher resolution but lower refresh rate. The Mega Drive can recognize 512 colors but can only display 61 at any one time. This is achieved through palettes, which work similarly to an artist's palette.
00:13:40.800 Each palette can contain 16 colors, with one color reserved for transparency, allowing for a maximum of 15 usable colors per palette. There are four palettes, therefore providing a total of 60 colors, plus one default background color, resulting in 61 colors.
00:14:38.639 All graphics on the Mega Drive are tile-based, constructed from 8x8 pixel tiles. The Mega Drive can display two background layers (often referred to as background and foreground) which can be scrolled separately. There are also sprites, which are common in 2D games—the two elephants you see at the bottom of the screen are sprites.
00:15:12.000 I’ll now demonstrate the scrolling feature I mentioned earlier. The Mega Drive has two background layers, which typically consist of a sky backdrop that scrolls slowly to the left, while the ground foreground moves faster to the right. This utilizes the VDP's hardware functions. You load the image into the VDP and simply tell it to adjust the scroll offset, which it does for you.
00:15:57.500 The Mega Drive certainly had its challenges, primarily the memory limitation of 64 kilobytes, which is quite small, even for MRuby/C. During development, I encountered many memory-related issues, which led me to implement manual optimizations. For example, I pre-rendered text as images instead of allocating string objects in MRuby, which could take up considerable memory.
00:16:58.640 By using the SGDK library, I could pre-render images directly into video RAM, making it much more efficient. Consequently, I found myself generating pre-rendered images for text and making several manual memory optimizations because I frequently ran out of memory.
00:17:40.080 When working on video game consoles, you typically don’t have output options such as logging or printf debugging. However, emulators like GENSK Mode provided nice features like console output, which allowed me to print any messages I wanted. Some of these emulators even support remote debugging connectivity with GDB, which I haven’t used yet.
00:18:36.840 Emulators are excellent for development, but they cannot fully replicate the experience of real hardware. Recently, I fixed a graphic glitch that only appeared on the Mega Drive itself, not in the emulators.
00:19:00.840 For instance, when you develop a Mega Drive game using SGDK with C, you need to write your C code, prepare resources like images and sounds, and cross-compile your C code. Typically, you are using Intel or ARM, but for the Mega Drive, you must produce a binary compatible with the 68k architecture.
00:19:43.200 SGDK provides a resource compiler that compiles your resource files into a single compiled resource file. After that, you put the compiled resources together with the SGDK library and other components like ROM headers to produce a ROM file that can be booted from a Mega Drive or emulator.
00:20:31.380 As for the resource declaration, I’ll show you what it looks like in my resource file. For instance, in my environment, I have a file called hp.png that I’d like to call RCT and make available in my program. This method allows it to become accessible in the program.
00:21:24.120 After declaring the resource in a header file, I create functions callable from MRuby and attach that function to a class, making it available in Ruby. Once declared, the actual Ruby code that calls the resource is straightforward.
00:22:20.160 Now, I’ll demonstrate a simple version of my presentation code. The core logic is written in Ruby, where it loops and waits for user input to show a new page.
00:22:38.880 I have developed a demo game which I created for Ruby Kaji in September. As you can see, the scrolling sky moves slower than the scrolling ground, while the spikes are moving faster.
00:23:02.820 There’s not much more to the game.
00:23:14.560 I would like to mention what I’ve intended to do between September and now. I haven’t made much progress as I had planned, but I wanted to create more games using this toolkit. Additionally, I wish to separate my modifications in the MRuby/C codebase, which has become mixed up over time.
00:24:34.560 There's a lot of manual optimization and boilerplate code involved when importing images and resources into my program. I aim to reduce that with better tooling. If you’re interested in something like this or if you have a Mega Drive and plan to create your own games, you can find the presentation code at the bottom. The top URL is for the game I'm about to demo.
00:25:50.520 Finally, I'd like to thank the MRuby developers, the MRuby/C developers, and SGDK developers. Without their awesome software, I wouldn’t have been able to accomplish what I have here today.