LlamaCore is essentially a Z80 system emulator for iPhone (and other devices). Unlike other Z80 system emulators, LlamaCore does not emulate a specific reality-based physical-hardware system, but rather a fictitious hardware platform heavily based on a few existing platforms.
The concept is that I love the challenge of writing in Z80 assembly code, and I love the aesthetic of the old-school, early 80s arcade games, simple sprites over a tiled background. I want to be able to write such games and applications for the iPhone.
As of 2009-Nov-04, LlamaCore does the following:
- Rom loading from the app bundle (can load any of 255 rom files for each of the 3 16k rom segments.)
- Basic monitor functions (display some registers, disassemble) step, run, etc.
- Device hardware memory mapped into Z80 memory space
- Touch events mapped into sprite screen coordinate space
- Accelerometer X,Y,Z values
- Device orientation
Here's a screenshot of the basic Z80 monitor.
The basic system consists of:
- Z80 Emulation Core - a Z80 CPU emulator. I'm using Udo Munk's Z80Pack.
- Graphics Rendering
- Sound playback
- User Interface
The Z80 emulator I'm using is based on Udo Munk's Z80Pack. I made a few modificiations to it to allow for external control, loading and saving of the Core to an arbitrary (not fixed) filename, and the loading of binary ROM images.
I Have then wrapped this into an Objective-C object, with some added Peek: and Poke: methods to allow for ram/rom snooping/injection.
Future improvements include encapsulating all of Z80Pack's globals into a structure, to allow for more than one Z80 core to be running at a time. (This is a nontrivial amount of busywork).
The Z80 core will be running unthrottled, and timing mechanisms will be employed using interrupts, rather than busy loops/fixed cpu speed timers. No watchdog timer will be implemented.
Some system functions might be accelerated within the Z80 core, such as memcopy, memset, bank switching, etc. These can acclerate screen scrolling and related functions.
The graphics will be achieved in an old-school method based on classic arcade hardware. It will consist of two levels;
- Tile-based background
- Floating sprites
The Tile-based background will be a memory-mapped buffer layout, similar to Pac-Man, Jr-Pacman, Gameboy, etc, where a byte in a specific memory location defines a specific 8x8px tile that gets loaded into the displayed tilemap.
As well, there will be scroll registers to allow for the system tilemap to be larger than the screen tilemap, and to be moved around smoothly.
Floating sprites will have Pac-like controls on them for screen position as well as rotation.
Graphics will be stored in the bundle as PNG files (with transparency for sprites) rather than binary, encoded ROM files, for ease of generation and support.
Color definition registers/control/tilemap from the original game architectures will likely not be implemented, and instead, the base colors will be taken from the PNG files, with tinting possibly implemented in the graphics engine instead.
Details are TBD.
I am implementing this section via the free cocos2D engine.
To simplify the engine, sound will be accomplished by having a pre-defined audio files in the native format of the device. Sound file playback will be triggered by a port IO or memory-mapped control register set.
Details are TBD.
Since the iPhone device has no joystick controls, a new user interface needs to be developed for games on this platform. A few ways this can be accomplished are detailed below.
All analogish range-based values will be presented in an 8 bit byte, range of 0..255, to represent [0.0 .. 1.0] where apprpriate.
Map the entire screen (or a D-Pad Overlay like "Wolf3D") to a standard joystick control. This will appear in the Core as Up/Down/Left/Right stick switch toggles. This is probably the most cumbersome for the end user.
Touches and triggers on the entire screen are represented in a memory mapped register set. Touches are represented as events/counts, with their location being mapped to a X/Y that corresponds with sprite X/Y positions. This allows for direct in-game representation of the user touches on the screen.
Of course, the device has a few other data inputs. These include screen orientation: Portrait, Landscape Left, Landscape Right, Portrait Upside-down, Face Up, Face Down. These are directly represented as a flag in the Core.
Another is accelerometer values. This is mapped as a series of values in memory. A sub-feature is the computations involved to determine the angle that points "up". In this case, it will be stored as an "upedness" value, where 0 is "up" Since these require extra hardware to be enabled, they will be only turned on if the game code requests it.