Friday, December 28, 2012

About non-JXD Actions Semi-based devices

I finally managed to get hold of the type of firmware that I believe was installed on the Kulala K-802 lookalike that I have since given away. It's from a device called "Ko W5000", and is identified as "P2 100423 int us225a 1027 100227" by the Product Tool. I have extracted the files from that firmware and found that, while it appears similar to the JXD MIPS devices, the OS is sufficiently different that it won't make sense to support it in my actsemi project.

So I won't look into this type of system, but if you want to you can download the firmware image and the files I have extracted from it.

Friday, December 21, 2012

Ewww, MIPS! (Spectrum emulator)

xpectrum for the SPMP8000


A week or so ago I have ported xpectrum (also known as gp2xpectrum, iXpectrum, Xpectroid, and Aunt Irma [citation needed]) to the SPMP8000 platform. There is no support for ZIP files (if built with zlib all files, even non-compressed ones, fail to load), and the scaling in full-screen mode is done in software, and not very well. Other than that, it works quite nicely, sound and virtual keyboard included. You can download it here, source code is at the usual place.

The A3300 is... different.


I actually wanted to fix the two issues with xpectrum before announcing it here, but I didn't find the time because I've been had. My JXD A3300 has arrived at about the same time I finished the xpectrum port, and when I tried to run the emulator on it, it didn't work! Apparently, the A3300 is not an SPMP8000 device at all, but based on some obscure MIPS controller by "Actions Semiconductor". A little online research indicated that nobody has done any homebrewing on this platform yet. Bummer.

Not so fast!


I was unwilling to write off this purchase, though, so I went ahead and extracted the data from the encrypted firmware update image for the A3300. (Load it into the firmware update tool, attach OllyDbg, find the largest data segment, dump it, remove some superfluous bytes, and you've got yourself an SQLite3 database file.)
As it turned out, this system is a very, very different beast, but in many ways every bit as crappy as the good old SPMP8000/eCos platform.

The Actions Semiconductor OS


The Actions Semi OS appears to be based on uC/OS-II. It features a dynamic loader and virtual memory, but nonetheless almost all interfaces are implemented using system calls, even the GUI and libraries like SQLite. There even is a memcpy() syscall, although most applications have the good sense not to use it. On top of that they put something that seems to borrow many conventions and architectural features from Unix/Linux, such as devices as files, the POSIX threads API, or file name endings (".so" for dynamically loaded object and ".ko" for kernel modules), but it is clearly not derived from Linux. It's probably a custom job, either grown in-house at Actions Semi, or contracted from a third party. The latter seems more likely to me because the strings found in the binary files are almost entirely void of Chinglish, very much unlike the SPMP8000 OS.

Running our own code


From what I could tell there is no mechanism similar to the "native game" loading on the SPMP8000 that would allow you to run third-party native applications. There is, however, an update mechanism that checks if there are new emulators on the externally accessible flash partition. To check for updates, the OS tries to load certain files (libp1.so, libg1.so, etc.) with dlopen() and inspects an exported symbol to get a version number. If the number is higher than the one of the installed emulator (or there is no emulator of that type installed yet), it will copy the new file over the existing one on an internal flash partition and use it as an emulator for the corresponding types of files from now on.
The neat thing here is that dlopen() automatically runs the code in the .init section of the binary, so I wrote a little program ("installer") that resides entirely in the .init section, and if you put a file called new_libp1.so on the external flash, it will copy that file over the internal PS1 emulator, before any version numbers are being checked. Now all we need is a MIPS ELF binary that conforms to a few simple standards, and we can run your own code on this "closed" platform by choosing any file that is configured to be run by the PS1 emulator in the file browser.

Getting comfortable


Of course this is not very convenient: You don't want to copy files around and run the installer every time you want to use a different program. So I wrote another program ("launcher") tailored to the Actions Semi emulator interface that pretends to be an emulator up until the point where the emulator framework tells it what "ROM" it is supposed to play. At that point it opens that file and checks if it is an ELF binary. If it is, it dlopen()s the file and relays all information it has previously received from the emulator framework. At this point, the new binary has hooked itself into the emulator framework and takes over. If the file to be played is not an ELF binary, the same thing happens, with the exception that it's the PlayStation emulator that is loaded. Now we can simply copy our homebrew code to the console and run it from the file browser, provided we give it a PlayStation-ey file extension; .bin seems like the obvious choice.

Doing something useful


What we need now is a substantial demo. Since I had played around with xpectrum anyway, I just went ahead and ported that as the first homebrew program for the Actions Semiconductors platform. It works every bit as well as the SPMP8000 port, except that it's even faster if you disable throttling. Here's how to try it:

WARNING: This is alpha-quality code, use it at your own risk. It is unlikely to cause any serious damage to your system, but I am not making any promises. It may also work on devices like the JXD 3000, 5000, and M1000, but it has only been tested on my JXD A3300.
  1. Download installer.elf and put it on the internal flash drive as "libp1.so".
  2. Download launcher.elf and put it on the internal flash drive as "new_libp1.so".
  3. Choose the game icon in the main menu to bring up the file browser; this will trigger the installation process.
  4. Connect the console to your computer. What you should see is that the file new_libp1.so has been deleted, and the file backup_libp1.so (and possibly backup_libp1+.so) have been created.
  5. Download real_libps1.so and put it on the internal flash drive. This is the PS1 emulator that will be used from now on. (You could use the backup files created previously instead, but the emulator has to be a specific version (R1.06), so it' s better to use the downloaded one.)
  6. Put xpectrum in the GAME directory.
Now you should be able to launch xpectrum from the file browser.

The Code


The following components are available for your enjoyment from the actsemi github repository:
  • libactsemi: A support library that provides access to the system call interface, which includes most standard C library functions and a lot of other things, from everyday stuff like semaphores and threads to a complete GUI interface, property lists, and text encoding functions, although many of them still lack prototypes and data type definitions.
  • Baselibc: A customized version of the small C library Baselibc that provides the stuff that the operating system doesn't, such as string functions. I chose it over newlib because the Actions Semi OS already provides a rather high-level interface through system calls, and it's not easy to make newlib cooperate with another C library.
  • installer: The binary injection program that replaces the PS1 emulator with our own code.
  • launcher: A replacement for the PS1 emulator to be installed by launcher that is able to launch both native ELF binaries and a PS1 game images.
  • demo: A simple moving-bar demo that also emits a lot of random debug output. I use it to test OS features.
The xpectrum code can be found in the actsemi branch of the SPMP8000 git repo.

To build all this goodness, you need a MIPS32 cross-toolchain. I built mine using crosstool-ng and this configuration file. Unfortunately, crosstool-ng doesn't pass the target CFLAGS that you set in the config file correctly when building newlib. While we don't use the newlib libc.a, this will still cause us grief when linking with the newlib math library. I worked around this by building newlib manually with CFLAGS_FOR_TARGET="-march=mips32r2 -G0 -Os".

Have fun!

Saturday, December 8, 2012

Documentation, more libraries, and a new ScummVM build

A quick update:
  • I doxygenized the code and you can find the resulting documentation here. There's a boatload of information on the various interfaces available, so if you have any interest in joining the fun, check it out.
  • There are four new libraries in the 3rdparty directory: libmad, libogg, libvorbis, and Tremor.
  • There is a new ScummVM build with zlib, MAD, and Tremor enabled, so you can play your compressed games now.
Have fun!

Tuesday, December 4, 2012

SPMP_SendSignal() Research (and ScummVM)

I did some rote work and added a new header file (mcatch_cmd.h) to the library that defines all the commands SPMP_SendSignal() accepts, 128 in total. I tried my best to guess reasonable names, but the only ones we can be sure about are those that are mentioned in debug strings. There is some really interesting stuff in there: power management, TV out, system update(!), SD card detection, various audio settings (speaker switching, volume, equalizer, Dolby), FM radio control, LCD panel control (suspend/resume, brightness), camera control, media playing, and much more.

SPMP_SendSignal() most often gets a pointer to a parameter structure that is used as input and/or output. So far I have only figured out the one used to read the real-time clock, in order to give ScummVM save games the proper timestamp.

And with that we come to our main attraction: ScummVM for SPMP8000 devices. This build only contains the SCUMM v1-v6 engine (memory is tight on this platform), but supports most features already, including sound and save games. The major feature that is not supported yet is compression, both for save games and game data. This is not difficult to fix, I simply haven't gotten around to it yet. Another feature I absolutely want to add is touchscreen support, but that will have to wait a bit; my A3300 is still in flight from China. :)

I have tested this build with Fate of Atlantis (VGA/Floppy) and Maniac Mansion (Enhanced), and they both work fine. It is quite conceivable that bigger games might not run due to a lack of memory, but that remains to be tested. Source code is at the usual place. Have fun!

[UPDATE: Here's the key mapping.

  • F5 -> START (brings up the in-game menu)
  • ESC -> SELECT (skip cutscenes)
  • Mouse cursor -> d-pad
  • Left mouse button -> O
  • Right mouse button -> X
]

Saturday, December 1, 2012

Win32 Toolchain (and a teaser)

I painstakingly built a Win32 (MinGW) arm-eabi toolchain, maybe that'll be of use to some people. Extract it in the root of your MinGW system. (Or, better yet, get yourself a real operating system, even if it's just Mac OS or something like that.)

Apart from the previously mentioned adbg and better support for building on Windows, the library has received a few small touchups:

  • The startup code, header files, and linker script have been made C++-ready.
  • The newlib/eCos glue translates stat()'s st_mode correctly now, so you can distinguish between files and directories.
  • The utility function libgame_chdir_game() changes to a well-defined directory (the "GAME" folder), making it easier to find data files.

And these unassuming little fixes allow us to do this:



(Yes, that's ScummVM. The photos have been taken with the JXDs, my apologies. :)

Stay tuned...