Sun Apr 20 14:31:21 EDT 2014

I can still fight you!

YU-NO - 始動

It's been quite a while since I have last posted here! Sorry for the website being down for like 3+ months... orz... The issue should be resolved. This post isn't about that though. I've made lots of progress with Hien in the time since the last post; here are some highlights:

  • No longer directly focused on sound emulation
  • Externally defined boards utilizing a set of markups and HDL programs
  • Dynamically compiled code for maximum performance
  • Extensive state logging, saving and loading
  • Emulated CPU profiling
  • YM2608 emulation (YM2610 is nearly done!)
  • Tons of cleanups and refactors

I said in the last post that Hien's goal was to be a sound-section emulator. In reality, that was just the first step. The choice to start as a sound emulator was made because I knew that it would give me a good base to work off of, and it's a simple enough goal that I could realistically achieve it while still trying interesting ideas. I think it was a good choice; it gave me a lot of experience with writing a flexible emulator base and let me focus on the actual core framework rather than things like how to handle video. At present, Hien still only emulates sound, but video and input are coming soon.

1943 Kai: Midway Kaisen - Air Battle 3

Hien's base concept has changed since the last post as well. Before, the game information was all built into the emulator. Now, everything is loaded from a series of external files that operate more like full PCBs rather than just being simple ROM data. The entire operation of the emulated machine is described in these files. Because Hien is now totally agnostic of what it's emulating, I've excised any mentions of the word "game" from the core; we now deal in the concepts of "virtual machines" (VMs), comprising one or more "boards". Each emulated board corresponds to a real physical board, so multi-board machines (CPS-I/II, Neo-Geo, Konami GX, etc.) will have two separate boards that the user is able to connect. Boards are specified independently of each other, which encourages interoperability and well-written board definitions. A series of boards and their connections may be specified from the UI, but a much easier approach is to use a board set file which contains a list of boards and how they are connected.

This concept of a board definition and separate boards might initially seem confusing and strange. Will this system require extra effort just to play games? On the contrary, it may even make it easier. A series of boards and their connections may be specified from the UI, but a much easier approach for those who just want to play a game is to use a board set file, which acts as a predefined arrangement.

This is all good and well, but what is meant by board definition hasn't properly been expressed yet. A board definition is a set of markups (YAML, specifically) and Domain-Specific Language (DSL) programs accepted by Hien, parsed and interpreted to generate metadata and real code to control emulation. The board emulation is not interpreted or anything like that past the initial setup phase; the definition handler creates and loads dynamic code for maximum performance and flexibility. There were a few reasons to pick the approach of externally defined boards, the biggest being that a huge monolithic program to emulate machines that you don't care about is antithetical to having a clean and efficient emulator. The other defining reason is the ability to add lots of extra metadata that could allow generating better or more efficient emulations without actually changing the board definition files. I could completely rewrite Hien from scratch and the board definitions would never have to change. The real power of this approach though, is that faster and more accurate emulations can be created with less effort.

A save state directory

A feature that was only added quite recently is the state logger, which contains a registry of emulated variables and device state. This isn't all too different from how regular emulators handle savestates, but the interesting and unique concept here is that we actually create a named path to each variable. When you save a state, it creates a full directory structure, and saves each bit of state into its own file. This allows for easy picking through device states. The most useful benefit of this approach actually isn't even in saving and loading states though; this also allows for very easy real-time manipulation of VM state, since device registers and such can be directly accessed and even browsed by name. An interesting usage for this capability is to allow modifiable parameters for an emulated device, to enhance its operation beyond the original capabilities. This could something as simple as modifying the channel balance or panning in a song, or something as complex as changing the interpolation method and parameters on a sampler sound chip. Of course, support for this sort of thing is required to be built into the device emulation, but it allows interesting possibilities for enhanced reproduction.

Profiler sample

The most recent feature added to Hien is the new CPU profiler, which profiles the emulated CPUs so you can see where all the action is going on inside the emulated program. You can pick and choose which CPUs in the VM you want to profile, and then view the profiler output externally with the helper tool prof_view. This feature should be extremely helpful for those developing their own programs for emulated hardware, or people who want to modify a game to have less slowdown. It's even a decent passing curiosity for anyone interested in just what makes something tick. Support for the profiler is extremely easy to add to an emulated CPU core, often requiring less than 15 lines of code and little-to-no reworking.

Touhou Kaikidan: Mystic Square - The Grimoire of Alice

Not really as cool as all the other awesome core work mentioned here, but the YM2203 emulation has been broken down into little modular bits to allow re-using as much code as possible for the other OPN-series emulations. To test this out, I decided to write the emulation stuff needed for the YM2608, most notably used in the NEC PC-98x1 series of personal computers. It was actually pretty simple to do, and made me implement some other things that should make doing the other OPN-series emulation cores pretty easy. Thus, YM2610 (used in Neo-Geo and many Taito arcade games) and YM2612/YM3438 (Mega Drive, FM Towns) should be fairly easy to do as well. Another result of this was that I broke out my ADPCM core from the OKI MSM6295 emulator, so that should be easily re-usable too. It's a minor, but also incredibly helpful change for the benefit of code re-use; there are an astonishing amount of similar ADPCM sound chips that merely use modified tables or additional channels or what-not (including the YM2608 and YM2610!).

Wrapping up the big changes, there have obviously been tons of refactors since the last post. The new usage of dynamic code has required significant reengineering and rethinking for how to handle boards and how to make everything fit together; the splitting up of several of the sound generators has required refactors in the entire device handling base to make everything mesh well; the sound playback engine is much more robust and cleaner; ROM loading has changed drastically due to the use of markup. This is all indicative of a flexible codebase that can fluidly adapt to new challenges and a solid design looking forward, rather than at its toes.

I hope this is mostly understandable and not just pointless ranting, but I think this project and concept has a bright future and I'm doing what I can to make it a reality. The next post I make will probably be mostly about the markup/DSL combination and how truly powerful and effective it is. There is still much work to be done before I think I can release it without regrets. Until then I'll try to give appropriate peeks into the development!

Posted by trap15 | Permanent link | File under: arcade, emulation, reverse_engineering, hien