tag:blogger.com,1999:blog-74972409374536238172024-02-18T18:55:06.373-08:00Uli's WIP EmporiumDingoo, SNES, and SPMP8000 antics.ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-7497240937453623817.post-23534460487781418652012-12-28T08:09:00.002-08:002012-12-28T08:09:52.246-08:00About non-JXD Actions Semi-based devicesI finally managed to get hold of the type of firmware that I believe was installed on the <a href="http://kulala.hk/prodetail.asp?pid=37">Kulala K-802</a> lookalike that I have since given away. It's from a device called "<a href="http://www.kocode.com/cpin_dange.asp?id=187">Ko W5000</a>", 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 <a href="https://github.com/uli/actsemi">actsemi project</a>.<br />
<br />
So I won't look into this type of system, but if you want to you can download the <a href="http://www.emulinks.de/actsemi/5.40.rar">firmware image</a> and the <a href="http://www.emulinks.de/actsemi/dump-us225a.7z">files I have extracted</a> from it.ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com16tag:blogger.com,1999:blog-7497240937453623817.post-90344047845509546712012-12-21T06:18:00.000-08:002012-12-21T14:36:32.707-08:00Ewww, MIPS! (Spectrum emulator)<h3>
xpectrum for the SPMP8000</h3>
<div>
<br /></div>
A week or so ago I have ported <a href="http://code.google.com/p/xpectrum/">xpectrum</a> (also known as gp2xpectrum, iXpectrum, Xpectroid, and Aunt Irma<sup> [citation needed]</sup>) 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 <a href="http://www.emulinks.de/spmp8k/xpectrum-r23.bin">download it here</a>, source code is <a href="https://github.com/uli/xpectrum-spmp8000">at the usual place</a>.<br />
<br />
<h3>
The A3300 is... different.</h3>
<div>
<br /></div>
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 "<a href="http://www.actions-semi.com/">Actions Semiconductor</a>". A little online research indicated that nobody has done any homebrewing on this platform yet. Bummer.<br />
<br />
<h3>
Not so fast!</h3>
<div>
<br /></div>
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. <span style="font-size: x-small;">(Load it into the firmware update tool, attach <a href="http://www.ollydbg.de/">OllyDbg</a>, find the largest data segment, dump it, remove some superfluous bytes, and you've got yourself an <a href="http://www.sqlite.org/">SQLite3</a> database file.)</span><br />
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.<br />
<br />
<h3>
The Actions Semiconductor OS</h3>
<div>
<br /></div>
The Actions Semi OS appears to be based on <a href="http://micrium.com/page/products/rtos/os-ii">uC/OS-II</a>. 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 <span style="font-family: Courier New, Courier, monospace;">memcpy()</span> 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 <a href="http://en.wikipedia.org/wiki/POSIX_Threads">POSIX threads API</a>, 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 <a href="http://en.wikipedia.org/wiki/Chinglish">Chinglish</a>, very much unlike the SPMP8000 OS.<br />
<br />
<h3>
Running our own code</h3>
<div>
<br /></div>
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 (<span style="font-family: Courier New, Courier, monospace;">libp1.so</span>, <span style="font-family: Courier New, Courier, monospace;">libg1.so</span>, etc.) with <span style="font-family: Courier New, Courier, monospace;">dlopen()</span> 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.<br />
The neat thing here is that <span style="font-family: Courier New, Courier, monospace;">dlopen()</span> automatically runs the code in the <span style="font-family: Courier New, Courier, monospace;">.init</span> section of the binary, so I wrote a little program ("installer") that resides entirely in the <span style="font-family: Courier New, Courier, monospace;">.init</span> section, and if you put a file called <span style="font-family: Courier New, Courier, monospace;">new_libp1.so</span> 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.<br />
<br />
<h3>
Getting comfortable</h3>
<div>
<br /></div>
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 <span style="font-family: Courier New, Courier, monospace;">dlopen()</span>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; <span style="font-family: Courier New, Courier, monospace;">.bin</span> seems like the obvious choice.<br />
<br />
<h3>
Doing something useful</h3>
<div>
<br /></div>
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:<br />
<br />
<b>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 i</b><b>t has only been tested on my JXD A3300.</b><br />
<ol>
<li>Download <a href="http://www.emulinks.de/actsemi/installer.elf">installer.elf</a> and put it on the internal flash drive as "<span style="font-family: Courier New, Courier, monospace;">libp1.so</span>".</li>
<li>Download <a href="http://www.emulinks.de/actsemi/launcher.elf">launcher.elf</a> and put it on the internal flash drive as "<span style="font-family: Courier New, Courier, monospace;">new_libp1.so</span>".</li>
<li>Choose the game icon in the main menu to bring up the file browser; this will trigger the installation process.</li>
<li>Connect the console to your computer. What you should see is that the file <span style="font-family: Courier New, Courier, monospace;">new_libp1.so</span> has been deleted, and the file <span style="font-family: Courier New, Courier, monospace;">backup_libp1.so</span> (and possibly <span style="font-family: Courier New, Courier, monospace;">backup_libp1+.so</span>) have been created.</li>
<li>Download <a href="http://www.emulinks.de/actsemi/real_libp1.so">real_libps1.so</a> 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.)</li>
<li>Put <a href="http://www.emulinks.de/actsemi/xpectrum-r35.bin">xpectrum</a> in the GAME directory.</li>
</ol>
<div>
Now you should be able to launch xpectrum from the file browser.<br />
<br />
<h3>
The Code</h3>
</div>
<div>
<br /></div>
<div>
The following components are available for your enjoyment from the <a href="https://github.com/uli/actsemi">actsemi github repository</a>:</div>
<div>
<ul>
<li><a href="https://github.com/uli/actsemi/tree/master/libactsemi">libactsemi</a>: 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.</li>
<li><a href="https://github.com/uli/actsemi/tree/master/Baselibc">Baselibc</a>: A customized version of the small C library <a href="https://github.com/PetteriAimonen/Baselibc">Baselibc</a> 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.</li>
<li><a href="https://github.com/uli/actsemi/tree/master/installer">installer</a>: The binary injection program that replaces the PS1 emulator with our own code.</li>
<li><a href="https://github.com/uli/actsemi/tree/master/launcher">launcher</a>: 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.</li>
<li><a href="https://github.com/uli/actsemi/tree/master/demo">demo</a>: A simple moving-bar demo that also emits a lot of random debug output. I use it to test OS features.</li>
</ul>
<div>
The xpectrum code can be found in the <a href="https://github.com/uli/xpectrum-spmp8000/tree/actsemi">actsemi branch</a> of the SPMP8000 git repo.</div>
</div>
<div>
<br /></div>
<div>
To build all this goodness, you need a MIPS32 cross-toolchain. I built mine using <a href="http://crosstool-ng.org/">crosstool-ng</a> and <a href="http://www.emulinks.de/actsemi/crosstool-mips.config">this configuration file</a>. 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 <span style="font-family: Courier New, Courier, monospace;">libc.a</span>, this will still cause us grief when linking with the newlib math library. I worked around this by building newlib manually with <span style="font-family: Courier New, Courier, monospace;">CFLAGS_FOR_TARGET="-march=mips32r2 -G0 -Os"</span>.</div>
<div>
<br /></div>
<div>
Have fun!</div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com14tag:blogger.com,1999:blog-7497240937453623817.post-5798019030777515492012-12-08T07:34:00.000-08:002012-12-08T07:35:11.852-08:00Documentation, more libraries, and a new ScummVM buildA quick update:<br />
<ul>
<li>I <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a>ized the code and you can find the resulting <a href="http://www.emulinks.de/spmp8k/docs/">documentation here</a>. There's a boatload of information on the various interfaces available, so if you have any interest in joining the fun, check it out.</li>
<li>There are four new libraries in the <a href="https://github.com/uli/libspmp8k/tree/master/3rdparty"><span style="font-family: 'Courier New', Courier, monospace;">3rdparty</span> directory</a>: libmad, libogg, libvorbis, and Tremor.</li>
<li>There is a <a href="http://www.emulinks.de/spmp8k/scummvm-1.6.0git-7e264.bin">new ScummVM build</a> with zlib, MAD, and Tremor enabled, so you can play your compressed games now.</li>
</ul>
<div>
Have fun!</div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com3tag:blogger.com,1999:blog-7497240937453623817.post-90519458360532677172012-12-04T03:11:00.000-08:002012-12-04T03:54:33.320-08:00SPMP_SendSignal() Research (and ScummVM)I did some rote work and added a new header file (<span style="font-family: Courier New, Courier, monospace;">mcatch_cmd.h</span>) to the library that defines all the commands <span style="font-family: Courier New, Courier, monospace;">SPMP_SendSignal()</span> 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.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">SPMP_SendSignal()</span> 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.<br />
<br />
And with that we come to our main attraction: <a href="http://www.emulinks.de/spmp8k/scummvm-1.6.0git-cc4e4.bin">ScummVM for SPMP8000</a> 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. :)<br />
<br />
I have tested this build with <i>Fate of Atlantis</i> (VGA/Floppy) and <i>Maniac Mansion</i> (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 <a href="https://github.com/uli/scummvm-spmp8000/tree/spmp8000">the usual place</a>. Have fun!<br />
<br />
[UPDATE: Here's the key mapping.<br />
<br />
<ul>
<li>F5 -> START (brings up the in-game menu)</li>
<li>ESC -> SELECT (skip cutscenes)</li>
<li>Mouse cursor -> d-pad</li>
<li>Left mouse button -> O</li>
<li>Right mouse button -> X</li>
</ul>
<div>
]</div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com3tag:blogger.com,1999:blog-7497240937453623817.post-24061516144845139362012-12-01T13:22:00.003-08:002012-12-01T13:23:01.029-08:00Win32 Toolchain (and a teaser)I painstakingly built a <a href="http://www.emulinks.de/spmp8k/arm-eabi-toolchain-mingw32-2.22.90-4.7.2-1.20.0.7z">Win32 (MinGW) arm-eabi toolchain</a>, maybe that'll be of use to some people. Extract it in the root of your MinGW system. <span style="font-size: x-small;">(Or, better yet, get yourself a real operating system, even if it's just Mac OS or something like that.)</span><br />
<br />
Apart from the previously mentioned <span style="font-family: 'Courier New', Courier, monospace;">adbg</span> and better support for building on Windows, the library has received a few small touchups:<br />
<br />
<ul>
<li>The startup code, header files, and linker script have been made C++-ready.</li>
<li>The newlib/eCos glue translates <span style="font-family: 'Courier New', Courier, monospace;">stat()</span>'s <span style="font-family: 'Courier New', Courier, monospace;">st_mode</span> correctly now, so you can distinguish between files and directories.</li>
<li>The utility function <span style="font-family: 'Courier New', Courier, monospace;">libgame_chdir_game()</span> <span style="font-family: inherit;">changes</span> to a well-defined directory (the "GAME" folder), making it easier to find data files.</li>
</ul>
<div>
<br /></div>
<div>
And these unassuming little fixes allow us to do this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRehYqyhAr0Knfp-0zWzAUjw1TeMCUODZDHDelz_PSJ54Z5f-DFrnLRkdEM_6py22JO79FigR9YoCYob2E4NPlbYYRiIj5ay8N6eiyKAEkYg_dUVu3pt7_NgtPubNt5E1LCd1b3gfKobk/s1600/SNAP0006.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRehYqyhAr0Knfp-0zWzAUjw1TeMCUODZDHDelz_PSJ54Z5f-DFrnLRkdEM_6py22JO79FigR9YoCYob2E4NPlbYYRiIj5ay8N6eiyKAEkYg_dUVu3pt7_NgtPubNt5E1LCd1b3gfKobk/s400/SNAP0006.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipx5F8hbBLjgOA1T2aNw2Gb-0h40wWaBj_8wWLpF_TG3ZmPUxjoqmYH4uZ-IKgxy90gZN8R7n_SGxQJp4ZwYLetTEM-m1B0B8j4F40-OjtRCCDAnOrPy_pL06fkS9GyO2bvFd0dL4kGF8/s1600/SNAP0010.jpg" imageanchor="1" style="clear: left; display: inline !important; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPuKaGrBgHAmnAdojcRupbOLoK5iHTFiBCFzMIaQKviZ3W6tZE7Qixlvqen-4X-p35MykzFyxo7-kIBlxc-dN8sg6RKf14dLzzu-96xe558JtJPY1ueXf-kW8VpUrqMjcgbbFu2dNMQVE/s1600/SNAP0008.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPuKaGrBgHAmnAdojcRupbOLoK5iHTFiBCFzMIaQKviZ3W6tZE7Qixlvqen-4X-p35MykzFyxo7-kIBlxc-dN8sg6RKf14dLzzu-96xe558JtJPY1ueXf-kW8VpUrqMjcgbbFu2dNMQVE/s200/SNAP0008.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZmKp06uCOXI54E3cEqvCOcaQGPptP7Ugo35lqdBdI45L8ffIvXsMdqVgsxJtI4ZlTMv8hzCO7jrZlxi8vweyHNG853dGxeFiPQJSnFtsPW4eJ4OG7-A9rCqqg72X07h0J1J1LeCBz2WY/s1600/SNAP0003.jpg" imageanchor="1" style="display: inline !important; margin-left: 1em; margin-right: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZmKp06uCOXI54E3cEqvCOcaQGPptP7Ugo35lqdBdI45L8ffIvXsMdqVgsxJtI4ZlTMv8hzCO7jrZlxi8vweyHNG853dGxeFiPQJSnFtsPW4eJ4OG7-A9rCqqg72X07h0J1J1LeCBz2WY/s200/SNAP0003.jpg" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipx5F8hbBLjgOA1T2aNw2Gb-0h40wWaBj_8wWLpF_TG3ZmPUxjoqmYH4uZ-IKgxy90gZN8R7n_SGxQJp4ZwYLetTEM-m1B0B8j4F40-OjtRCCDAnOrPy_pL06fkS9GyO2bvFd0dL4kGF8/s1600/SNAP0010.jpg" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipx5F8hbBLjgOA1T2aNw2Gb-0h40wWaBj_8wWLpF_TG3ZmPUxjoqmYH4uZ-IKgxy90gZN8R7n_SGxQJp4ZwYLetTEM-m1B0B8j4F40-OjtRCCDAnOrPy_pL06fkS9GyO2bvFd0dL4kGF8/s320/SNAP0010.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;">(Yes, that's <a href="http://scummvm.org/">ScummVM</a>. The photos have been taken with the JXDs, my apologies. :)</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
Stay tuned...</div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com4tag:blogger.com,1999:blog-7497240937453623817.post-90063632202084200362012-11-29T05:44:00.001-08:002012-11-29T05:51:20.498-08:00Debugging SPMP8000 Programs Without Soldering<div>
As everybody knows, the best way to debug code is to print lots of crap to the console, not the least because that requires very little platform support: All you need is a place where you can dump data and where it can be retrieved later. On the SPMP8000, I have so far used the file system for that purpose: Just redirect <span style="font-family: Courier New, Courier, monospace;">stderr</span> to a file and write everything there. There is, however, a big problem with that approach: On a system without memory protection, programming errors usually result in a system crash, which in turn leads to total loss of the logged output. A better solution would be to have a channel of communication from which the debug output can be read as it is written, such as a serial port.</div>
<div>
<br /></div>
Luckily, all SPMP8000 microcontrollers come with an on-chip serial port, and breaking it out seems simple enough: Most devices appear to have soldering pads where you can attach wires. So I set out to perform this operation on my JXD 100 and promptly ripped the soldering pad off the board when I tried to verify whether the solder joint is good. Determined to make this work, I then attempted to solder the TX wire directly to the leads on the microcontroller, with a soldering iron that, at its narrowest, is about as wide as two pins. Predictably, I ended up shorting the UART TX and RX lines, and I suppose the JXD 100 is now happily talking to itself when printing debug output. I briefly tried to aggravate the situation by using a knife to scratch out the solder between the pins, but luckily came to my senses before causing more serious damage.<br />
<div>
<br /></div>
<div>
So what now? After some contemplation I came up with an alternative solution that does not require any hardware shenanigans and thus allows me to keep my white gloves on and my hardware alive: using the line out connector as a serial port.</div>
<div>
<br /></div>
<h3>
The audio debugging interface (<span style="font-family: Courier New, Courier, monospace;">adbg</span>)</h3>
<div>
<br /></div>
<div>
The latest feature in <a href="https://github.com/uli/libspmp8k">libspmp8k</a> is the <span style="font-family: Courier New, Courier, monospace;">adbg</span> debug interface. It takes your debug output, serializes it and sends it to the headphone jack. When you connect that to the line input on your PC and run <span style="font-family: Courier New, Courier, monospace;">adbg_console.py</span> there, it will decode the signal and print the debug output to your console. No soldering, no need to employ serial-to-USB converters, just plug in a cable and you're done.</div>
<div>
<br /></div>
<h4>
The Catch(es)</h4>
<div>
<br /></div>
<div>
Of course nothing is ever that simple, and there are a few things that you have to keep in mind:</div>
<div>
<ul>
<li>If you get no output at all, make sure to you have turned up the volume up to the maximum on both the transmitting and receiving ends. We want as much clipping as possible to get a nice square wave. You may also have to tell<span style="font-family: Courier New, Courier, monospace;"> adbg_console.py</span> which input it should listen to.</li>
<li>If you usually get correct output, but there are bursts of garbled data, make sure you have good sound hardware with good drivers on the PC side. My computer at work (HP desktop with Intel HDA sound, Linux kernel 3.4.x) inserts random bursts of noise into the input signal every once in a while and is therefore largely unusable for this application. The machine at home (EVGA 780i SLI FTW board, also Intel HDA, kernel 3.1.x), on the other hand, works without a hitch. YMMV.</li>
<li>Your computer may be oddly wired. If you receive output, but it's all garbled, you may have to invert the signal (<span style="font-family: Courier New, Courier, monospace;">adbg_console.py</span> option "<span style="font-family: Courier New, Courier, monospace;">-i</span>").</li>
<li>There is no error detection or correction, nor is there a back channel, so this is not something you can or should use to transmit data that has to be 100% error-free.</li>
<li>The devices I have seen so far (JXD 100 and A1000) seem to detect the presence of headphones by impedance. A line input has a much higher impedance that headphones and is therefore not detected. This is not a problem for signal transmission because the output on the headphone jack seems to be always on anyway, but it will be a problem for your ears because the internal speaker will not be switched off. You can, however, switch the speaker off manually in the "Settings" app.</li>
<li>Finally, you have to disable sound in your program when debugging because it would interfere with the debug signal.</li>
</ul>
<div>
For an example of how to use audio debugging, check the <a href="https://github.com/uli/libspmp8k/tree/master/demos/adbg"><span style="font-family: Courier New, Courier, monospace;">adbg</span> demo</a> in the <a href="https://github.com/uli/libspmp8k/tree/master/demos">demos directory</a>. The console program <span style="font-family: Courier New, Courier, monospace;"><a href="https://github.com/uli/libspmp8k/blob/master/tools/adbg_console.py">adbg_console.py</a></span> can be found in <span style="font-family: Courier New, Courier, monospace;"><a href="https://github.com/uli/libspmp8k/tree/master/tools">tools</a></span>.</div>
</div>
<div>
<br /></div>
<div>
The console application is written in Python, supports ALSA and PortAudio, and requires <a href="http://pyalsaaudio.sourceforge.net/">pyalsaaudio</a> (for ALSA) and/or <a href="http://people.csail.mit.edu/hubert/pyaudio/">PyAudio</a> (for PortAudio) to be installed. ALSA is of course Linux-only, but using PortAudio it should work on Windows and Mac OS X as well, although I have not tested that.</div>
<div>
<br /></div>
<div>
Have fun!</div>
<div>
<br /></div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com1tag:blogger.com,1999:blog-7497240937453623817.post-28548970425299880332012-11-23T15:42:00.003-08:002012-11-23T15:43:39.427-08:00xrick for SPMP8000Here's a port of <a href="http://www.emulinks.de/spmp8k/xrick-r15.zip">xrick for the SPMP8000</a> platform. I always wanted to be the first to port the most ported game of all times to a "new" platform. :) Source code is at <a href="https://github.com/uli/xrick-spmp8000">the usual place</a>.<br />
Please note that I have only tested this build on the JXD 100 because my wife brought the A1000 on a trip, so I can't use it for development ATM.<br />
<br />
There are a few new features in <a href="https://github.com/uli/libspmp8k">the library</a> as well:<br />
<br />
<ul>
<li>A couple of new test firmwares (JXD A16, 2000, and 300); all passed the tests without any changes.</li>
<li>I have added two <span style="font-family: 'Courier New', Courier, monospace;">NativeGE</span> hooks I found in the A16 firmware, <span style="font-family: 'Courier New', Courier, monospace;">NativeGE_SPUCommand()</span> and <span style="font-family: 'Courier New', Courier, monospace;">NativeGE_getTPEvent()</span>. I have no idea what the former does, but the latter obviously allows you to poll for touchscreen events. I do not have a touchscreen SPMP8000 device (yet), so I cannot test this right now.</li>
<li>Followed a suggestion by Sea S to fall back to the HZX16 font if the Sunplus fonts are not available. This is a phenomenon I have never encountered in any official firmware, but there seem to be custom firmwares with those fonts removed.</li>
<li>I have exposed <span style="font-family: 'Courier New', Courier, monospace;">_putc</span> (and named it <span style="font-family: 'Courier New', Courier, monospace;">_diag_putc</span> to avoid clashing with newlib). It's the character output function used by <span style="font-family: 'Courier New', Courier, monospace;">diag_printf()</span>, which is used for all operating system debug output. By redirecting it to your own implementation you can, for instance, redirect system debug output to a file.</li>
</ul>
<div>
Have fun!</div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com3tag:blogger.com,1999:blog-7497240937453623817.post-21902144266604896492012-11-15T02:13:00.000-08:002012-11-23T15:44:27.684-08:00Better SPMP8000 Homebrewing (and PC Engine emulator!)I recently got myself a JXD A1000 and found it quite an enjoyable device to develop for. The "official" API ("native game" interface) isn't any fun, though: Fixed screen size of 320x240, no access to all but three buttons, no support for generated audio, no access to the ROM file system, not even a way to list directories.<br />
<br />
The firmware is, of course, able to do much better than that, but while all the functionality is there, we don't know how to access it: function and memory addresses are different from device to device and from firmware revision to firmware revision. While it was easy to adapt, for instance, Triple Oxygen's libemu for the Cybergame to my A1000 to get sound support, the result would again only run on a single machine. I didn't really want to spend a lot of time developing software that won't run on other people's systems, so I did some thinking and came up with a solution: On-the-fly firmware reverse-engineering.<br />
<br />
Whenever I found something interesting in the firmware, I devised a simple heuristic that weasels its way through the running operating system, usually starting from a function the address of which we know because it's part of the "official" interface, and taking advantage of typical subroutine calls, address loads, debug strings, and function table offsets to get to the sweet stuff in a way that works on all SPMP8000 firmwares. To check that it really does work everywhere I availed myself of eleven different firmwares (and an additional JXD 100) and wrote a test harness that verifies that the heuristic actually arrives at the right spot.<br />
<br />
<a href="https://github.com/uli/libspmp8k">The result is a library</a> that provides you with a greatly extended API in a portable fashion, so your programs will (hopefully) run on any SPMP8k device. Here's the stuff you couldn't get before:<br />
<ul>
<li><b>Emulator interface: </b>This is the API used by the built-in emulators. It provides hardware scaling from arbitrary resolutions, access to all keys on all controllers (both raw scan codes and standardized mappings), and streaming audio.</li>
<li><b>Frame buffer access: </b>Direct access to the currently active display device's frame buffers, with support for single and double buffering.</li>
<li><b>eCos POSIX-like file API:</b> Access to all files without restrictions or filtering. Full set of directory functions. (Seriously, with the official API you can't even read a directory!) I have glued this interface to newlib, so you can use stdio functions (<span style="font-family: 'Courier New', Courier, monospace;">fopen()</span> etc.).</li>
<li><b>High-resolution timer:</b> The official API gives you mere 100 Hz; with the new <span style="font-family: 'Courier New', Courier, monospace;">libgame_utime()</span>, you can get microsecond resolution. Indispensable for accurate speed and profiling.</li>
<li><b>CPU scaling: </b>Saves battery power, you can go down as low as 5 MHz. (Sorry, no overclocking.)</li>
<li><b>Built-in fonts: A</b> few simple routines I wrote to use the bitmap fonts in ROM. Not as black magic as the other stuff, but with full Unicode support. :)</li>
</ul>
<div>
There's more stuff in there, like the mysterious <span style="font-family: 'Courier New', Courier, monospace;">SPMP_SendSignal()</span> function that takes dozens of commands, or the eCos threading interface, that I will unearth as needed. I also more or less worked out the signatures of all the as-yet undocumented functions in both the "native game" and the emulator API, if you want to experiment a little.</div>
<div>
<br /></div>
<div>
Using this souped-up libspmp8k, I have ported <a href="http://www.emulinks.de/spmp8k/">PC Engine emulator TGEmu</a>, and it runs like hell <span style="font-size: xx-small;">(after some optimization) </span>on both the JXD A1000 and 100, and probably on your SPMP8000 device, too. Check it out! (You need PC Engine ROMs, of course. Uncompressed, zipped, and gzipped files are supported.) <a href="https://github.com/uli/tgemu-spmp8000">The source code</a> should also give you a good idea of how to use the library. Have fun!</div>
ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com16tag:blogger.com,1999:blog-7497240937453623817.post-81217536623987027412010-07-18T12:46:00.000-07:002010-07-18T12:46:03.773-07:00snes-sdk updateAfter about a year I finally got around to do something with <a href="http://code.google.com/p/snes-sdk/">snes-sdk</a> again. I fixed it to build (ahem), and added some of the optimizations from a tool called <a href="http://nesdev.parodius.com/bbs/viewtopic.php?p=60051">optimore</a> to the peephole optimizer. (I do not recommend to use optimore, BTW. I have found at least some of the optimizations to cause test suite failures...)ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com0tag:blogger.com,1999:blog-7497240937453623817.post-19103572514856525042010-07-03T12:16:00.000-07:002010-07-03T12:16:28.831-07:00Linux and the built-in flashI don't know if this is generally known, but I've been digging into the original firmware, and it appears that the flash translation layer used for the internal memory is NFTL. At least some left-over debug strings strongly point in that direction. NFTL is readily supported by the Linux kernel, but there's a problem: When I enable the jz4740 NAND flash support in the opendingux kernel, it freezes at some point during bootup, so I cannot test my assumption.<br />
<br />
(Also tried the legacy kernel, but it wouldn't even compile with NFTL enabled.)ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com15tag:blogger.com,1999:blog-7497240937453623817.post-80006849462839698252010-06-25T09:41:00.000-07:002010-06-25T09:41:45.620-07:00/dev/memHacking on my <a href="http://github.com/uli/qemu-vfb">"Dingux emulator"</a>, I recently came across some applications that behaved rather erratically. So I looked into the source code of one of them, and I found that while the application itself uses SDL throughout, the Dingoo-specific GUI tacked on mmap()s the JZ4740 I/O registers to get user input. This, of course, spectacularly and needlessly fails on everything that is not a Dingoo A-320.<br />
<br />
Here's some advice: Once you have chosen one level of abstraction, you stay there. And when you're porting somebody else's code who chose to develop on top of SDL, you also stay there, whether you like it or not!<br />
<br />
And, generally, using /dev/mem to sidestep the operating system is wrong. Always.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://images.cheezburger.com/completestore/2010/6/25/c26d8f69-b554-4460-be2f-4b4509ae7961.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://images.cheezburger.com/completestore/2010/6/25/c26d8f69-b554-4460-be2f-4b4509ae7961.jpg" width="320" /></a></div><br />
Unless you're me, of course. But even then it's a hack. Thanks for listening.ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com0tag:blogger.com,1999:blog-7497240937453623817.post-32311102582049624152010-06-20T04:09:00.000-07:002010-06-20T04:09:10.075-07:00gmenu2x hogs my CPU no moreNot sure if anyone ever noticed that, but gmenu2x wastes enormous amounts of CPU time (20-30%) by constantly redrawing the screen when there's absolutely nothing going on. So I made a quick fix that makes it redraw the screen on user input only.<br />
<br />
Commit: http://github.com/uli/gmenu2x/commit/c2c1c375d21c1872e2c47a661d9aae0d0227e5d5<br />
Binary: http://github.com/downloads/uli/gmenu2x/gmenu2xulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com2tag:blogger.com,1999:blog-7497240937453623817.post-14928376089899848732010-06-19T09:45:00.000-07:002010-06-19T09:53:52.377-07:00something to play with for the weekendHere are binaries of an opendingux kernel with TV-out ioctl and CPUFreq, a matching "tvout" tool, and a fixed gmenu2x that doesn't mess up the display:<div><br /></div><div>http://github.com/downloads/uli/dingoo-tvout/zImage-opendingux-9325</div><div>http://github.com/downloads/uli/dingoo-tvout/zImage-opendingux-9331</div><div>http://github.com/downloads/uli/dingoo-tvout/tvout-opendingux</div><div>http://github.com/downloads/uli/dingoo-tvout/gmenu2x-opendingux</div><div><br /></div><div>Have fun. This appears to be much more stable than the previous userspace-based hack.</div><div><br /></div><div>Source code repos are here:</div><div>http://github.com/uli/opendingux-kernel</div><div>http://github.com/uli/dingoo-tvout/tree/opendingux</div><div>http://github.com/uli/gmenu2x</div><div><br /></div><div>Have fun.</div>ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com3tag:blogger.com,1999:blog-7497240937453623817.post-65178785567108702322010-06-19T04:54:00.000-07:002010-06-19T04:56:35.841-07:00opendingux-kernel workI created an <a href="http://github.com/uli/opendingux-kernel">opendingux-kernel fork</a> on GitHub yesterday, and added some of my stuff:<br /><br /><ul><li><a href="http://github.com/uli/opendingux-kernel/commit/6f5fdc42bf95cdb8d48af285fb5a536d11d60b5d">FBIOA320TVOUT ioctl</a>, which is the LCD controller part of <a href="http://github.com/uli/dingoo-tvout">dingoo-tvout</a> done properly in the kernel where it belongs. There is a corresponding dingoo-tvout <a href="http://github.com/uli/dingoo-tvout/tree/opendingux">branch</a> that makes use of it.</li><li><a href="http://github.com/uli/opendingux-kernel/commit/9fd12ba393d4e710a17d76ad9552357124bfa33b">CPUFreq driver</a> based on the ubiquitous jz_cpuspeed() function. This driver is not perfect yet (TV image loses sync for a brief moment when changing frequencies, and too rapid rescaling breaks USB networking), and definitely needs some adjustments for coding style, but it is already way better than the currently preferred method of messing with the PLL and dividers in userspace.</li><li>Port of the <a href="http://github.com/uli/opendingux-kernel/commit/58307cc67bc699d245d5d31a78a95fdc464d78aa">/proc/jz interface</a> from the Ingenic kernel. I like it, it's good for debugging clock stuff.</li></ul><div><br /></div>ulihttp://www.blogger.com/profile/00789030620750383789noreply@blogger.com4