zeta0134 / LuaGB

A gameboy emulator written in pure Lua. Work in progress.
BSD 3-Clause "New" or "Revised" License
410 stars 33 forks source link

ComputerCraft/OpenComputers port #35

Open polyzium opened 4 years ago

polyzium commented 4 years ago

Using Love2D is nice and all, but I want to see this emulator being put to the test. CC/OC provide one of the harshest (IMO) Lua environments there is, with text graphics, suckass threading and more interpretation.

I don't know how would it be possible to port to ComputerCraft, but porting to OpenComputers would take less effort due to its Unicode support. And that means we can use Braille characters for bitmap graphics (the font draws them as pixels)+having 2 colours per cell/character that would resemble something like Commodore 64's colour limitations. As for sound, there would be no sound. Unless we use Computronics' sound card that has primitive shapes but lacks DPCM wave capabilities.

If Lunatic86 (pure Lua x86 emulator) did it, you can do it too.

zeta0134 commented 4 years ago

Ooh, so I actually did this a while back as a quick test, just to see if it works. It totally does, if you crank OpenComputers memory way up from its default, and if you're very, very patient. Screenshots:

opencomputers_ml2 opencomputers_la1

opencomputers_la2

Unfortunately, since OpenComputers doesn't have a JIT (last I checked), performance is abysmal, and the computer spends so much time idling that keyboard input doesn't work very well. So... technically possible in theory, but in practice it's just way to inefficient to be useful. To take those screenshots, I literally started the emulator and made dinner while waiting for frames to advance.

I think it might be possible to write a simplified LCD implementation and get a Gameboy implementation partway there, but other than the novelty of doing it, I'm not willing to expend a whole lot of effort for the port. LuaGB has an open license though, so feel free to take a stab at it yourself. The main thing you'll need to contend with is the "bit" library and the RAM limitations, but if you can get that patched in it should more or less run without too much modification. (Please don't try to run it on someone else's server though; it is a heavy program.)

polyzium commented 4 years ago

I think there are ways to speed the thing up, but I might be wrong because I never wrote an emulator and I don't have that much experience with low-level programming.

So, like I feared, OC is way too slow for anything related to emulation, but it supports Lua VM bytecode that you can compile your emulator into (I don't think we'll ever get a LuaJIT arch anytime soon), maybe that will make it faster? Haven't tried it but could work.

As for the implementation itself, Lunatic used lots of hacks to get it to work in some way, x86 is one of the toughest arches overall. Using hacks is always a bad sign in theory but works in practice, maybe that'll help with the optimization. At least Lunatic is usable. RAM shouldn't be a problem...

polyzium commented 4 years ago

Oh and one more thing: where can I get the OC ported version from? There doesn't seem to be a branch or anything that contains it, I'll try compiling it to bytecode and see if that helps.

zeta0134 commented 4 years ago

Hrm... I don't think this port ever saw the light of day. It wasn't really a proper effort, more of a test. The gameboy module itself requires very little alteration to work on a pure Lua implementation (OpenComputers, ComputerCraft, etc) but the shell will need to be redone obviously, since it heavily depends on Love2D. Basically, pull down the git repo, include the "gameboy" folder as a module, do something about the missing "bit/bit32" calls, then call the functions.

If I get a moment I can put together a proof of concept, but I'm rather distracted by IRL obligations for the moment, so no promises.

polyzium commented 4 years ago

After spending some time, I developed my own port with (WIP) Braille-based rendering. And it's alive! Running in OCEmu at max speed, the emulator reaches a framerate of ~1fps. No input yet. image image The palette is kinda screwed up tho - you can barely see that Pikachu has bright green cheeks. image image image

ghost commented 3 years ago

I'm currently porting LuaGB to a custom version of ComputerCraft that supports higher resolution monitors:

image

It is indeed very slow, though not the "go make dinner" kind of slow. And since I'm already using a custom version of ComputerCraft I do have some intention of attempting to optimize it.

ghost commented 3 years ago

Switched my custom version of ComputerCraft to the experimental CCLuaJIT implementation: https://github.com/sci4me/CCLuaJIT

At half resolution it is playing at full speed now, but drawPixel is unfortunately slowing it down at full resolution, time to optimize the pixel rendering code.

Looks like the blit() function is much more efficient, going to switch to that.

ghost commented 3 years ago

Success! Using the blit() function it now runs at full speed! Though due to the minecraft tickrate you're currently only able to actually see 20 fps.

Next up is the audio emulation, this one is a bit tricky, but very fun. We'll need to use the Computronics Sound Board for this, which doesn't (directly) support the PCM audio that LuaGB generates. What it does support is AM and FM which is actually a much better fit for the gameboy. I'll simply cut out all the sample generation and translate directly to the Sound Board API using this excellent guide: https://gist.github.com/Vexatos/28ec1d7e79fd7b251b1832edec515104

polyzium commented 3 years ago

Damn, it has been almost a year... I would very much like to see LuaJIT in OpenComputers... It has been a long while since I used CC as I've switched to OC as soon as I saw the Unix-like environment in it. Good to see CC (or at least their derivatives) has pixel support now. Drawing bitmaps in OC is kinda tricky due to Braille characters the default font provides (funscii, asie's fork of viznut's unscii). As for audio, I don't think Computronics provides a pulse wave with an adjustable pulse width, only 50% iirc. Recreating those in AM/FM is going to be tough.

ghost commented 3 years ago

It wouldn't be fun without a bit of a challenge, besides if there's an unreasonable limitation we can just compile a custom version of Computronics as well.

Also I'd be very interested in expanding LuaGB to support the Super Gameboy colors. With only 16 colors available on the entire screen in ComputerCraft we can't do Gameboy Color emulation, but we can definitely support the Super Gameboy.

Also thanks a lot for your work on LuaGB @zeta0134, it's been super fun working with the code base. 👍

polyzium commented 3 years ago

The GBC has 16 colours too, what's the problem? Unless the palette is hardcoded, that is. Same for OC Tier 2 GPU snd screen, Tier 3 ones have 256 colours.

ghost commented 3 years ago

Doesn't the GBC have 8 different palletes for the sprites? According to wikipedia the gameboy color supports:

Palette colors available: 32,768 (15-bit) Colors on screen: Supports 10, 32 or 56

I definitely like OC more as a computer, but for these kinds of projects I think CC is a better fit. I actually have both running on my server, so I can use OC as my in-game computer and CC as my gameboy emulator with a huge multi-block screen.

zeta0134 commented 3 years ago

The GBC has 16 palette entries, but the LCD operates in full 15-bit color mode at all time. Because games can write to palette memory mid-screen, the full range of colors that can be displayed at one time is essentially infinite. As a quick example, Pokemon Puzzle Challenge uses mid-frame palette updates to create a gradient effect in the sky on the title screen.

I'm still trying to find my jaw somewhere on the floor; I wasn't aware LuaJIT was even an option within Minecraft, and you seem to have gotten it working way better than any of my attempts. Bravo!

ghost commented 3 years ago

It's really thanks to @sci4me for getting LuaJIT working in ComputerCraft that it's even possible to run at full speed. I'm just in charge of gluing all the great works by others together. :+1:

Once I've gotten audio working I'll create a Pull Request here so that CC support can live next to Love2D support if you'd like it to. I get the feeling getting this working in Minecraft was always your intention, it just so happens that now is the right time for it.

ghost commented 3 years ago

So looking more into the audio side of things, it looks like we actually do need some rudimentary PCM support since the wave channel is essentially PCM audio, albeit only with very short segments.

Computronics is also missing a way to change the duty cycle of the pulse channels as @polyzium pointed out, so we will also need a custom build of Computronics with both the additions of small PCM audio segments and a duty cycle for square waves if we want an accurate representation of the gameboy audio.

ghost commented 3 years ago

Though the wave channel is going to be hell for Computronics given how Pokemon Yellow abuses it: https://youtu.be/fooSxCuWvZ4?t=360

polyzium commented 3 years ago

Any way to detect it? You can pump it into the tape drive and play it back. I do realize this is a gross hack, but it works

ghost commented 3 years ago

It's an interesting solution, we'll see, let's focus on the games that don't abuse the audio chip first.