PDA

View Full Version : zerox86 progress



wraggster
August 4th, 2013, 19:27
via http://zerox86.patrickaalto.com/zblog.html

For the past weeks I have been on my summer vacation, and I decided to spend my vacation mostly not programming at all. Thus I have not made much progress with zerox86 either. However, I could not resist spending a few hours every few days working on either rpix86 or zerox86, whenever I got momentarily fed up with just being lazy. :-) For zerox86 I have worked on four specific issues: Fixing the annoying race condition, implementing Sound Blaster Direct DAC support, implementing a virtual keyboard, and finally I also began implementing the configuration display.
Fixing the race condition problemI began working on the race condition problem by coding a logging system that logged all IRQ-related events into a ring buffer. I could not log them directly to the file, as that changed the timing of the events so that the race condition did not occur, at least not as often. When the program then stopped because of the race condition, I wrote the ring buffer contents to a log file.
After a couple of attempts at studying the log, I finally understood the race condition. Sometimes the timer signal interrupted the audio thread (which in turn has interrupted the main thread), and because of a complex interaction between the main thread turning interrupts on or off and marking an interrupt handled, and the other threads queuing interrupts, it was possible for the system to get out of sync. Rather than attempting to fix the already too complex thread locking system, I decided to try rewriting it all using Linux real-time asynchronous signals.

The timer IRQ emulation already used the asynchronous SIGALRM signal, and I coded additional signal handlers for the other emulated IRQ lines, and also added new routines that any thread could use to send a signal to the main thread:
static void TimerIRQ() { IRQRequest(0); }static void KeyboardIRQ() { IRQRequest(1); }static void MouseIRQ() { IRQRequest(3); }static void SBIRQ() { IRQRequest(7); }static void PS2IRQ() { IRQRequest(12); }void SendKeyboardIRQ() { pthread_kill(maintid, SIGRTMIN+1); }void SendSBIRQ() { pthread_kill(maintid, SIGRTMIN+7); }void SendMouseIRQ() { pthread_kill(maintid, SIGRTMIN+3); }void SendPS2IRQ() { pthread_kill(maintid, SIGRTMIN+2); }void SendSIGTERM() { pthread_kill(maintid, SIGTERM); }The pthread_kill functions send a signal to the thread ID given as the first parameter, so calling the Send... routines from whatever thread always sends the signal to the main thread (which is where the actual emulation happens). IRQRequest is the common routine that handles the various IRQs in the main thread, and the static methods above are the actual signal handlers. I also added the program exit to the same system, so I can send the SIGTERM signal from any thread and handle it cleanly in the main thread. Now I was able to code the actual IRQRequest routine so that I did not need to use any thread synchronization mechanisms, as it will always get called within the main thread context. The only thing I needed to protect against was a new signal attempting to interrupt the handling of the previous signal. I decided to block all the used real-time signals in the beginning of the IRQRequest routine, and then later unblock them at the end, so that took care of that problem. In other routines in the main thread I simply used the ll and sc MIPS ASM opcodes to protect against interrupted execution. Since only the IRQRequest can interrupt the main thread, and not the other way around, this was sufficient locking for the variables shared between the IRQRequest code and the main thread. These changes seem to have fixed the race condition, as I have not encountered the problem any more.
Sound Blaster Direct DAC supportNext, it occurred to me that using interval timers for the TimerIRQ emulation allowed me to support very high timer speeds (like 8400Hz as used in Star Control 2) as long as the GCW0 kernel supports high-resolution timers. This makes it possible to have the timer interrupt routine play a single audio sample, which is what the Sound Blaster "Direct DAC" method does. So, I decided to enhance my Sound Blaster emulation so that it can play samples buffered by the timer interrupt routine. Because the actual audio playing rate I use in zerox86 is 22kHz, I still need to convert the samples from 8.4kHz (or whatever the game uses) up to 22kHz, and thus I need to buffer them before playing them. This buffering may cause some skips to the audio, but the audio still seems to sound mostly correct.
Implemented preliminary virtual keyboard.I also implemented some code to handle the keyboard image you can see in the screen copies of the previous blog post. I decided to use the SELECT key to toggle between activating the virtual keyboard (which then uses the D-Pad and A keys) and disabling it (which leaves D-Pad to emulate cursor keys and A to emulate Enter). I also tested using the amalog controller for the key selection, but noticed that it was too awkward to quickly select the correct key with that. Separate D-Pad key presses to move to adjacent virtual keyboard keys seems to work better.
Implemented preliminary config display.Finally, I also worked on displaying the current configuration (including a key mapping legend). This is something that I have wanted to do for a long time now, and I wanted to get it done before starting the actual configuration system, so that I can see that the configuration system works properly. Here below is a screen copy of the preliminary config and key legend display. It uses the lower 40 scanlines of the screen to display the configuration in use, and the currently mapped keys. Using the SELECT key you can toggle the screen bottom area to show either this display or the virtual keyboard. I will perhaps also add a third option that will show nothing, in case this display is distracting in some situations. I think I will need to still make this config screen somewhat cleaner, but in principle the visual layout is now in place. The values it shows are currently just placeholders for the actual values. I used those to determine the space I need to reserve for the key code names. The next step is to have it show the proper values currently in use.
My summer vacation ends today, so I will get back to the normal daily routine, and hopefully get some proper progress done to zerox86 as well.