Quantcast
Channel: dreamlayers
Viewing all 120 articles
Browse latest View live

Introducing an SDL 2 version of Em-DOSBox

$
0
0
When I first got my Emscripten port of DOSBox working, I was happy with the sound. It was not perfect. There were occasional small glitches at some CPU intensive moments. However, it was perfect most of the time in Firefox and pretty good in Chrome. (IE 11 does not support sound and IE 12 will hopefully support it in the future.) Then Firefox discontinued its Mozilla Audio Data API, and Emscripten began using the Web Audio API in both. That made Firefox sound significantly worse. When I recompiled Em-DOSBox with a recent version of Emscripten, sound was very bad.

I always had doubts about the way Emscripten's SDL plays audio via the Web Audio API. I don't think AudioBufferSource nodes are designed to be played one after another in a continuous stream. If it worked well, I wouldn't care about theoretical correctness, but it doesn't seem to work very well, so this may be a problem. I think the obvious way to play continuous sound from JavaScript is using a ScriptProcessorNode. (Those are depreciated, but their replacement, Audio Workers, are not implemented yet in browsers.)

I just found that SDL 2 has been ported to Emscripten. It is an actual port of SDL itself, not an SDL-compatible library like what is currently found in Emscripten. Looking at its audio code, I saw it using ScriptProcessorNode, and I decided to give it a try.

There is DOSBox SDL 2 patch by NY00123. It's based on a later version of DOSBox, but Git makes dealing with such things fun. First I merged with that revision of DOSBox, and then I merged the patch.

At first, sound was totally terrible. Then I found that the SDL callback needed float data, because ScriptProcessorNode needs floats. When I made that change, the sound was pretty good. It still isn't as good as old Firefox with the Audio Data API, but I think it's acceptable.

There is a problem with red and blue being swapped, and DOSBox won't run in IE, but SDL 2 for Emscripten definitely shows some promise. It may even be faster than Emscripten SDL, because more of it consists of C code which gets compiled into asm.js. Here is the Em-DOSBox branch.

The DOSBox FPU emulator and ole2disp.dll

$
0
0
Running Netscape 3 in Windows 3.11 caused Em-DOSBox to fail with an "FPU stack underflow". At first I couldn't reproduce this in DOSBox in Linux, but then when I recompiled with --disable-fpu, I reproduced it.

DOSBox has two FPU (floating point unit) emulators. One is used by default when running DOSBox on x86 hardware. It uses actual x86 FPU instructions, and it should provide the full 80-bit long double precision. The other one does not require x86 hardware, and uses standard doubles. That means it does not give the full precision one would expect from a real FPU.

In OLE2DISP.DLL 2.3.3027.1, there is a check for precision loss. The code loads a 64-bit integer using FILD, stores a 10 byte BCD number using FBSTP, and then tests the last four digits. If the digits aren't correct, it pops another value, causing the stack underflow.

Normally, this would cause an FPU underflow exception to be noticed by Windows, but DOSBox doesn't pass on those exceptions and instead quits emulation. This is of course an inaccuracy in CPU emulation. DOSBox isn't a very good general purpose x86 CPU emulator, partly because it is a hybrid of an operating system and CPU emulator. DOSBox is designed for running old games and good at that, but not general purpose emulation. I'm tempted to try to port Bochs to make a better general purpose emulator available. For now, I simply disabled the FPU stack underflow check, because that allows many Windows 3.x apps to work.

Here is an image of execution diverging after the test. I used this to find the location where the test was. Note that due to relocations, searching for this in files can be tricky. The image at the right is from the very helpful http://ref.x86asm.net/coder32.html table.



Finally, here's some x86 assembler code performing this test. This fails in DOSBox 0.74 in 64 bit Linux, but works in my SDL 2 branch, which is based on r3869. This is probably due to r3851. I hadn't written a DOS assembler program in so long, so this was fun:

; FPU test like OLE2DISP.DLL 2.3.3027.1
; Build using: nasm ole2disp.asm  -o ole2disp.com
segment code
    org 100h

; This is the test
    wait
    fild qword [input]
    wait
    fbstp tword [output]
    nop
    wait

    mov dx, header
    mov ah, 9
    int 21h

; This displays output
    mov cx, 10
    mov si, output+9
    std
outloop:
    mov al, [si]
    shr al, 1
    shr al, 1
    shr al, 1
    shr al, 1
    call outdig
    lodsb
    call outdig
    loop outloop
    int 20h

; Display a single hex digit.
outdig:
    xor ah, ah
    and al, 0fh
    mov bx, hex
    add bx, ax
    mov dl, byte [bx]
    mov ah, 2
    int 21h
    ret
 
segment data
input:   times 6 db 0
         db 0dfh, 00dh
output:  times 10 db 0
hex:     db "0123456789ABCDEF"
header:  db "FILD, FBSTP FPU test like OLE2DISP.DLL 2.3.3027.1", 13, 10
         db "00999517642299539456 is correct result. "
         db "Last 4 digits of following must match:", 13, 10, '$'




Fixing the hard problem in Em-DOSBox using Emscripten emterpreter sync

$
0
0

If you just want to use this

Use Emscripten incoming until a new version is released, after 1.29.4. Configure with: ./configure --enable-sync --with-sdl2 . The dosbox.html.mem file that is produced must be in the same directory as dosbox.js. The .mem file is big, but will compress well. Ensure your web server can serve files in compressed format. Ideally pre-compress them so they don't need to be compressed repeatedly.

Technical explanation

I previously wrote about the hard problem with porting DOSBox to Emscripten. Basically, DOSBox cannot easily work as one Emscripten main loop. I had an idea about how I could modify functions to make them resumable, but it would be messy and many functions would need modifications.

Fortunately, around the same time I learned about a new Emscripten feature: emterpreter sync. Instead of compiling to JavaScript, Emscripten can compile functions to a bytecode, and include an interpreter for that bytecode. Code running in emterpreter can be interrupted using emscripten_sleep(). This will call JavaScript setTimeout() and stop execution. The timeout function will then restore state as if the emscripten_sleep() call returned.

There is a catch here. Code running in emterpreter will run much more slowly than asm.js JavaScript. It is far too slow for DOSBox. The solution is to only use emterpreter for functions which could be interrupted by emscripten_sleep(). This means all functions that may be on the call stack when calling emscripten_sleep(). JavaScript functions must not be in the call stack, because their state cannot be resumed.

Once again, the way DOSBox is structured is a problem. The CPU interpreter can recursively call itself, leading to emscripten_sleep(), but emterpreter would make it too slow. A reasonable compromise is possible there: preventing sleep during those nested calls. They are typically CPU exceptions which should return quickly, so there is no need for sleep there.

The main remaining problem is the DOSBox paging code. It recursively runs the CPU interpreter, and only returns when execution returns to where the page fault occurred. This is a problem if execution never returns there, or another page fault happens and they don't return in a last in first out order. This is also a problem with ordinary DOSBox, but it is worse with Em-DOSBox. DOSBox would just run slowly and Em-DOSBox would hang the browser. A timeout check is used to prevent browser hangs.

Finding all the functions which require emterpreter was made easier by linking with -profiling, then using csplit dosbox.js '/^function /''{*}' to split up functions and using grep to search for calls. Using console.trace() at the start of emscripten_sleep() is also helpful. If an abort occurs after a resume, the previous backtrace will show what function requires emterpreter. Note that -O3 is required, because otherwise functions may have too many local variables for emterpreter.

Originally emterpreter only supported a blacklist of functions which should not use emterpreter. That was unusable in this situation due to the number of functions and changing name mangling of some. Alon Zakai helpfully added a whitelist, so functions which need emterpreter can be listed instead. Right now, there are 40 functions on that list. That's a small number compared to the thousands of functions in Em-DOSBox, but manually transforming all those functions to make them resumable would be a lot of work. It would also complicate use of new changes from SVN or applying of DOSBox patches. Based on performance and compatibility with DOS games, emterpreter sync was the right choice.

SDL 2 text input and Emscripten

$
0
0
SDL 1 used SDL_EnableUNICODE() to enable and disable text input. It started off disabled, and you needed to call SDL_EnableUNICODE() if you depended on the unicode member of SDL_keysym.

SDL 2 has a different text input API which is designed to accommodate international users and touchscreen devices. There, SDL video initialization turns on text input if an on-screen keyboard is not needed. This is normally harmless, it causes a problem in the Emscripten port. 

Normally, many keys trigger browser actions. Those actions should be prevented if you want to use the same keys in an SDL application. In Firefox, it is possible to prevent browser actions from keypress events, but in Chrome, Safari and IE they need to be prevented in keydown events. However, preventing default actions from keydown events prevents keypress events which are needed to get text characters.

If you need to prevent browser actions and don't need SDL 2 text input, simply disable text input after initializing SDL video:
if (SDL_IsTextInputActive()) SDL_StopTextInput();

You can find more information about these JavaScript events on quirks.org. They also have a test page which you can use to examine their behaviour on different browsers.

HTTP/2 is being used as a tool to promote encryption, and I approve of that

$
0
0
When I read that Firefox and Chrome will only allow encrypted HTTP/2 connections, I was shocked and disappointed. The standard itself does not require encryption, so this is an intentional limitation that those browsers chose to add.

Encryption by itself can only be trusted if you can be sure who you're talking to. Otherwise, you could have an encrypted connection to an adversary, who then makes an encrypted connection to the web server you wanted to reach. Because of this, web servers need certificates from recognized certification authorities. Without a trusted certificate, web browsers show scary warnings, as if something is horribly insecure. Firefox also makes getting around that warning annoying. In reality, such an encrypted connection is no worse than an unencrypted connection. It could be better, but you have no proof of that.

Because of these warnings, if you want to set up an HTTP/2 server, you effectively require a certificate from a recognized certification authority. This is an unprecedented limitation! The need to register somewhere to run a web server is reminiscent of what a totalitarian state might do. You generally even have to pay money, as if HTTP/2 is shareware with nag screens if you don't register.

Then I learned that StartSSL is offering free dynamic DNS and certificates. This means you can get a subdomain and associated recognized certificate for free. This gives you a way to use HTTP/2 for free, and you can probably also avoid supplying accurate personal information. It definitely helps, but having just one company in the whole world offering this isn't good.

What finally changed my opinion was thinking about the big picture. We know that there is extensive eavesdropping going on, by entities which have absolutely no respect for privacy. You can choose to use encryption wherever possible by installing HTTPS Everywhere, but many sites still don't support encryption or don't have it properly configured. HTTP/2 is being used as a tool to induce sites to start supporting encryption. What is being done with HTTP/2 may seem wrong, but it is being used to fight against something that is far more wrong. So, I think requiring encryption with HTTP/2 is justified.

Perhaps the best thing here is how those implementing new technology are leveraging that power, and not giving it away.

The Dell Inspiron 6400/E1505 hinge switch is easy to remove

$
0
0
My laptop would sometimes wake up from sleep while closed. After some searching online I learned about the hinge switch. Replacement switches are inexpensive, but the replacement procedure seemed complicated and involved removing the top half of the laptop.

After opening up the laptop, I found that the switch can be removed without removing the top half. Just the hinge cover and keyboard are in the way. After unplugging the switch cable beneath the keyboard, the switch can be carefully manoeuvred out.

The hinge cover was the worst part. It's easy to open the screen 180 degrees and pry it up via the slot on the right, but the clips at the left side didn't disengage easily. I was afraid I would break something, but after looking at some videos I just continued, with carefully distributed force and some wiggling. The keyboard is easy to move out of the way, with just two screws at the top and easy pry points near Backspace and Esc. There is no need to unplug it, but be careful to not put stress on the flexible cable.

I also tightened screws connecting hinges to the bottom part of the laptop. They were a bit loose and this improved things, but the plastic itself flexes anyways. The top half would need to be opened up to tighten the hinge screws there, and that involves a lot of plastic clips.

I simply took the switch out and didn't replace it. I don't think I'll miss it. It's such a tiny delicate thing! Whoever designed that part of the laptop is an idiot. I assumed they would be using a magnet and reed switch or hall effect sensor.

This picture is with the switch removed. Its location is behind the black sleeved WiFi antenna cables where they enter the top half. The oval shape of the plastic where the wires enter actuates the switch.

Where is the iPodLinux kernel source?

$
0
0
iPodLinux is a Linux distribution for iPods based on PortalPlayer chips: the old hard disk based iPods up to the 5th generation, and the 1st generation Nano. It's actually a port of uClinux, because the processor lacks the memory management hardware needed for ordinary Linux. iPodLinux consists of a kernel port, the Podzilla application which provides an iPod-like interface, and various modules for Podzilla which are in effect small programs.

I have iPodLinux installed on my 5th generation iPod. It's interesting but not very useful for me. I normally run Rockbox, and I've only used iPodLinux for running Smartmontools smartctl to check hard disk health. Nevertheless, I'm interested in learning more about the Linux kernel, so I just spent some time tracking down the kernel source code.

Source locations

The old home page at www.ipodlinux.org has been down for a long time. Don't bother trying Archive.org, because the site wasn't archived due to its robots.txt.

There is an ipodlinux SourceForge project. Its files section contains patches and binaries. The latest 2.4.24-ipod2 version there is old and does not contain PP502x code needed for 5th generation iPods. If you want to use it, get linux-2.4.24, apply uClinux-2.4.24-uc0.diff and then apply the ipod2 patch. You can build with the arm-elf-tools-20030314.sh toolchain.

The same SourceForge project also has a SVN repository which has a later version. The kernel was initially at trunk/linux/ and then in r2251 "The Great Befuddlement" moved it to linux/2.4/. The repository only contains changed files, so you have to take an unmodified Linux directory, apply the uClinux patch, and then copy files from the repository into that tree. This kernel builds with arm-elf-tools-20030314.sh and works with my iPod. The repository seems abandoned, with the last commit in 2009. For convenience I'm providing a Git repository of just the kernel.

The SVN repository also has a 2.6 port at linux/2.6/ but it's at a very early stage. It might partially work with some older iPod, but it certainly won't have full functionality. I didn't even get it to compile successfully yet.

The uClinux-2.4.x patches starting with uClinux-2.4.24-uc1.diff.gz also contain iPodLinux code. It seems to be a stripped-down version of the ipod0 code, meaning it's very old. This complicates attempts to upgrade later iPodLinux to a later kernel version version, but it wasn't too hard to do with a git merge.

The latest version?

Finally I found ipodlinux on GitHub. The linux-2.4.32-ipod kernel seems to contain everything from the SourceForge SVN repository, but it switches over to uClinux 2.4.32 earlier, so it is not an exact copy. After that it contains some iPod specific patches, and then various Linux fixes.

The repository contains the entire kernel, so you can simply build from there. It is meant to be compiled with a later version of the toolchain. I used arm-uclinux-elf-tools.tar.bz2 with GCC 3.4.3. It compiles without problems and works on my 5th generation iPod.

Installing the kernel

You need to convert the kernel to a binary linux.bin image. Take a look at the instructions on SourceForge. Since I mainly use Rockbox, I have the Rockbox bootloader installed. It loads /linux.bin from the FAT32 partition if I hold down the play/pause key at the bottom of the wheel. You need a separate Linux partition for iPodLinux. If you need to resize partitions, be careful, because the original firmware partition is marked as unused but is actually required.

Binaries

There are some binaries at http://rvvs89.ucc.asn.au/ipl/. This includes a Linux-2.4.32-ipod2-cc.bin.gz kernel which I was using previously. I cannot find the source for that kernel. I just installed the new kernel I compiled from GitHub source.

SansaLinux

The V1 Sansa players also use PortalPlayer chips. SansaLinux seems to be an adaptation of iPodLinux to those players. In some parts kernel code is the same but "ipod" has been replaced by "sansa". I have not investigated this in depth. It could potentually have some useful new PP502x functionality.


Porting Rockbox to the RCA RC3000A digital boombox

$
0
0
This is an old post that I didn't get around to completing, and kept as a draft. It talks about how I ported Rockbox to the RCA RC3000A digital boombox. Code is available on GitHub.

Summary

First I opened it up and noted the chips inside. Some already have Rockbox drivers. Then, I figured out how to use USB boot mode to run code using tcctool with slight modifications. I used code to dump the firmware, outputting data via a GPIO pin and reading it via the sound card. Then I did some reverse engineering, figured out various functionality, got a Rockbox bootloader running, got Rockbox running and finally made playback work.

The LCD

First, I wanted a better form of feedback than GPIO pin toggling, so I figured out the LCD. The LCD command and data writing routines can be reached by following subroutine calls from a function that displays strings on the LCD. Then, other functions can be identified which use these functions to do stuff with the LCD. The initialization sequence was interesting. Instead of writing register indexes and then writing data to those registers, some commands have a command number in the high bits and data in the lower bits. I identified the controller by searching through Rockbox LCD driver files for | (which is bitwise or in C). The lcd-archos-bitmap.c driver for the graphical LCD on old Archos devices seemed like a match, so the LCD controller is probably a SSD1815. However, the initialization routine uses different values because the LCD panel is different, and it's important to use those values.

The call to the LCD initialization routine was surrounded by other interesting and relevant code. Just before the initialization, a call to a long function set the TCC760 chip select register for access to the LCD. Instead of trying to understand the function, I simply executed it in ARMSim to get the value. There was also a nearby GPIO call which controls the backlight.

Now it was possible to execute some code and write to the LCD. I thought building even a Rockbox bootloader would be difficult, so I just used a modified lcd-archos-bitmap.c file. This worked, but there was nothing interesting to display. I also verified that the nearby GPIO controlled the backlight. This was tricky, because although the CPU and LCD can run from USB power only, the backlight requires external power.

Building a Rockbox bootloader

This success made me want to try running more of Rockbox. I first decided to build a bootloader, because it uses only selected components of Rockbox. The Rockbox Wiki provides some basic information about how to create a new target. I started off by copying files from the Sansa C100, which uses the related Telechips TCC770 CPU. There were plenty of things to edit and rename, but it was all fairly straightforward, and error messages can serve as a guide showing what needs to be done.

Uploading code to SDRAM

The resulting bootloader was too big for loading in TCC760 internal SRAM, so I needed to use DRAM. Unlike with later chips, USB boot mode doesn't provide a way to set the SDCFG register. So, I used a small bit of assembler code to set SDCFG and then jump back to 0 to restart USB boot mode and enable uploading of a longer program to SDRAM. It was easy to get the bootloader running, but timer interrupts took a bit more work. The TCC760 is similar to TCC770, but there are some key differences with some peripheral register bits.

Figuring out the buttons

The bootloader allowed viewing of GPIO and ADC values which helped me figure out the buttons and some other values. The power/play/pause button is connected to its own GPIO pin, but all the other buttons are connected to one pin, with each connecting it to ground via a different value resistor. This means the ADC must be used to read these buttons. I ended up finding the original firmware routine which reads buttons and using its thresholds between different buttons. I suppose that's better than using measured values, because the measured values are affected by resistor tolerances.

SD card access

The RC3000A has 512MB of internal NAND flash storage, and an SD card. I chose to first use the SD card, because that seems safer. When I viewed GPIO values, I found pins for SD card write protect and SD card detection. I used these to find the SD card code. ARM code typically loads a base address into a register and then accesses a memory mapped peripheral register using that register plus an offset encoded into an instruction. In this case, 0x80000000 is always loaded into the register, so the offsets are predictable and they can be used to search disassembled code for GPIO access with few false matches. There is one unfortunate complication though. All the code I've seen makes the GPIO port obvious, but some uses a value loaded from RAM to define the bit.

I assumed that the SD card uses bit banging because there is no SD controller and USB access to the card is ridiculously slow. I did find bit banging code, but actually the SD card is hooked up to GSIO0, and there is also code for that. I chose to initially use bit banging code, because it is simpler to be sure I'm doing it correctly. GSIO could have left me wondering if the problem was the way I'm using GSIO or the interface to the SD card.

SD card bit bang SPI interface code can be used to add SD cards to routers, and source is available there. However, I chose to start with code from within Rockbox, from the Archos Ondio MMC card driver. Its structure more closely matches my intended final structure, with GSIO and hopefully also DMA.

After learning about the SD card protocol and commands, I first worked on getting initialize_card() working. At first this seemed futile, but then I added the initial synchronizing code sending 0xFF bytes with chip select not asserted and it worked. Then I just had an endianness issue in card_extract_bits() and after that the function succeeded. Then it was simple to read a sector.

Building Rockbox, adding functionality, and getting sound

(Post was interrupted here and continued much later.)

Once SD card reading was available and mountable, it seemed like a good time to run a full build of Rockbox. Since this includes files and functionality not compiled into the bootloader, some work was needed to get it to compile. Then it was time to add more functionality.

First I added I2C support, testing it using the E8564 RTC chip, which Rockbox already supports. The RC3000A uses purely software based bit-banging I2C, although the TCC760 chip does contain an I2C controller. 

I wanted to first set up the CODEC for FM radio playback, which should be simpler than music playback. At first I thought I could use the CS42L55 code present in Rockbox, but the CS42L51 is significantly different, so I ended up creating a new driver using parts of the Linux driver. I got the radio working using the pre-existing TEA5767 driver. Only the headphone jack was usable, because the amplifier driving the speakers was off.

Then it was time to do various tweaks to CODEC and I2S configuration and make playback work. However, the result was interrupted playback, because the device was too slow. I enabled the CPU caches, and started using GSIO for SD card access, and sped up the SD clock. Finally, I got perfect playback of a FLAC file.

Cleanups, tweaks and optimizations

There was still a lot of optimizing to do. The fast internal RAM in the TCC760 could be used to speed up code. Thumb and INIT_ATTR could free up memory. The SD driver needed more work. DMA could be used for playback.

I spent a lot of time trying to get DMA to work with GSIO for SD card accesses, but it seemed impossible and eventually I gave up. I optimized things the best I could with 16 bit GSIO transfers.

Getting USB to work was interesting, because I had never worked with a USB device before.

There were a lot of features to support. Rockbox includes various LCD settings such as flip and inverse, and a way to display greyscale on an LCD which doesn't officially support it. I also enabled sound bass and treble setting via the codec and backlight PWM fading.

Flashing the bootloader

So far, Rockbox could only be loaded via USB boot. It time to flash a Rockbox bootloader with dual-boot support, allowing for choosing between original firmware and Rockbox. I was a bit anxious because this could brick the device, but there was no real danger because USB boot should allow recovery.

Initially, I was thinking I would create a flash plugin and use it to flash the bootloader. However, I ended up creating a firmware upgrade file and flashing it via the original firmware. My first attempt allowed access to original firmware, but failed to run Rockbox. After adding some short initialization code from the original firmware I could load Rockbox.

The end?

Once I had a working Rockbox port, I stopped working on this. The RCA RC3000A devices are probably quite rare, and I've never encountered anyone else interested in running Rockbox on one. It doesn't even seem like there's any interest in running Rockbox on TCC76X devices. Therefore, I don't think adding this port to Rockbox would benefit anyone.

One thing that still interests me is making use of the OHCI USB host controller on the device. The original firmware supports it but fails badly when accessing a large device because it tries to scan all the files and keep a list in memory. I wonder if there's a good free software embedded USB stack? The SeaBIOS code might be useful, but it is GPL 3 and Rockbox is GPL 2.

I've also thought about adding an ESP8266 module and creating a Rockbox plugin for playing Internet radio. Such a plugin could also be used with other targets with externally accessible serial ports, such as the iPods.

Getting iPod hard drive SMART data via iPodLinux

$
0
0
Hard drives found in iPods generally support SMART. It is useful for checking drive health and running tests. The flash-based diagnostic mode reports only a few of the attributes. Rockbox lacks support for USB mass storage features which would allow programs running on a computer to use iPod hard drive SMART functions. I believe the original firmware's disk mode and the emergency disk mode in flash also lack this support.

Fortunately, there's iPodLinux. With some changes it's possible to cross-compile smartmontools for iPodLinux and run it there. Here's a link to the modified smartmontools-6.1 source with the smartctl binary inside. I did this quickly a while ago. I'm sure it's possible to port smartmontools more elegantly, but this works.

I find iPodLinux text input annoyingly inefficient, so I prepared three text files with these common commands:

smartctl -d ata -a /dev/hda > sao
smartctl -d ata -t long /dev/hda
smartctl -d ata -t short /dev/hda


You must specify -d ata to tell smartctl what type of interface to use. I'm sure it's possible to improve the port to remove that requirement.

Zooming out in Google Maps and Earth without multitouch

$
0
0
The Android versions of Google Maps and Google Earth are optimized for multi-touch. Double clicking zooms in a set amount, but the way to zoom out with a mouse isn't obvious.

To zoom in or out, double click, but don't release the second click. Keep holding the button and drag the mouse up or down to zoom in or out.

Audacious plugin for opening folder where files are located

$
0
0
I've been using Winamp for a long time. With a stripped-down configuration and the 2.x interface it is perfect. It supports a lot of formats, plugins and a playlist. With a nice skin it looks good, but takes up very little screen space and resources. I'm used to playing files from folders, and not using any sort of database.

Audacious seems to be the best replacement for Winamp in Linux these days. Its default interface is too big and plain, but it supports Winamp 2.x skins. It also uses plugins to implement various functionality and has an even better plugin API than Winamp.

There didn't seem to be any equivalent of the Winamp "Find File on Disk" plugin, so I created one. This gist contains the source code. To use it, right click on a file in the playlist, go into the "Services" sub-menu and select "Open File Location". You can also select multiple files in the playlist, and they will all be selected in the file manager.

Right now the plugin is written to use the KDE Dolphin file manager, which offers the nice --select flag. I'm not sure how to make this automatically work well with any file manager.

Compiling the iPodLinux 2.6 kernel

$
0
0
Normally, iPodLinux uses a Linux 2.4 kernel. The SVN repository on SourceForge also has a 2.6 kernel. It's an abandoned work in progress which lacks some drivers and support for PP502x iPods. Nevertheless, it may be a good starting point.

The port is based on Linux 2.6.7 with linux-2.6.7-hsc0.patch.gz applied. (This is the MMU-less ARM patch. It was mainlined in later 2.6 kernels.) Then, the iPodLinux files need to be copied into that tree, overwriting some Linux files.

This runs into several problems. Building with the old GCC 2.95.3 toolchain fails because the assembler is too old. With arm-uclinux-elf-tools.tar.bz2, the assembler is fine, but old GCC options are used, which aren't accepted by GCC 3.4.3. There are also two other small errors, and one error preventing make menuconfig. I'm distributing a fixed version in the form of a bare Git repository. It successfully builds linux.bin, which I didn't try to run because I don't have an old PP5002 based iPod.

One build problem remains: make always rebuilds everything. I'm not sure what's going on. If I run make -n --trace after successfully building linux.bin, I see a lot of stuff being re-built due to FORCE, as if this is intentional.

Optimizing Emscripten SDL 1 settings

$
0
0
Emscripten's SDL tries to emulate desktop SDL. This involves some costly operations which many programs don't need. Performance can be improved by changing settings to prevent those operations.

Consider the multiple copies

The image exists in 3 places in the web page: program memory, canvas ImageData, and the canvas element. Normally, SDL_LockSurface() copies from the canvas, to ImageData and then to program memory, and SDL_UnlockSurface() copies from program memory to ImageData and to the canvas. Conversion may be needed between program memory and ImageData.

SDL.defaults.copyOnLock = false

SDL_LockSurface() will copy from canvas to ImageData but not from ImageData into program memory.

SDL.defaults.discardOnLock = true

SDL_LockSurface() will use createImageData() once to initially create ImageData, and never copy from the canvas. Copying from ImageData to program memory is prevented regardless of SDL.defaults.copyOnLock.

SDL.defaults.opaqueFrontBuffer = false

With normal SDL you can write only the RGB values and get opaque pixels of the requested colour. Canvas pixels also have an alpha value, which needs to be set to 255 to make pixels fully opaque.

Normally, both SDL_LockSurface() and SDL_UnlockSurface() set alpha values in ImageData to 255. This option prevents those operations. With it, the SDL_HWPALETTE 8 bpp mode works normally, your code that writes pixels into memory must set the alpha values. You can simply bitwise or pixels with Amask from the surface SDL_PixelFormat.

Use SDL_HWPALETTE flag for 8 bpp modes

It's possible to use 8 bpp without SDL_HWPALETTE. However, that uses less optimized code when converting to 32 bpp for the canvas, and doesn't work with SDL.defaults.opaqueFrontBuffer = false.

SDL_HWPALETTE requires that SDL_LockSurface() copying is disabled. 8 bpp modes without the flag don't have that requirement, but you'll end up with 32 bpp RGB values copied back, which you probably don't want.

Module.screenIsReadOnly = true

This prevents SDL_LockSurface() copying. You could use it instead of SDL.defaults.discardOnLock = true. The only difference is that ImageData is copied from the canvas the first time SDL_LockSurface() is called instead of being created via createImageData(). It's probably better to use the SDL.defaults options instead because they're better documented and better named.

Sample code

Here is a code fragment which sets uses the recommended optimization settings and enters 8 bpp mode in the recommended way. Some of this is redundant as noted above, but there's no harm in that.

EM_ASM(
    SDL.defaults.copyOnLock = false;
    SDL.defaults.discardOnLock = true;
    SDL.defaults.opaqueFrontBuffer = false;
);
surface = SDL_SetVideoMode(WIDTH, HEIGHT, 8, SDL_HWPALETTE);

My favourite music visualization program running in a web browser

$
0
0
Synaesthesia is my favourite music visualization program. I created an updated Windows port and also ported it to Emscripten. The code is on GitHub. Here is a screen shot, but you have to see it in action to really appreciate it.


Click here to run the program. Then start visualization by dragging an audio file from a file browser window on your computer to the web page. No information is sent over the network. The file is played by the web browser and visualized by asm.js running in the browser.

If you find that Firefox can't play MP3 files in Linux, install gstreamer1.0-fluendo-mp3.

Goodbye KDE!

$
0
0
I switched to KDE when GNOME 3 was released. Over time, version 4 generally got better and less buggy. I was satisfied and even happy with it. Now Plasma 5 seems to have thrown away a lot of that progress. There are far more bugs and less features. It's not as bad as the GNOME 3 change, but Plasma 5 is bad enough that I don't want to use it.

It's tragic how these free software desktop environments get to be good and then revert to a state which should be called an alpha release. Of course GNOME 2 and KDE 4 had some limitations and disadvantages. A big bold change can help there, but I think the only way to truly improve is to slowly evolve into something better. Even Microsoft can't successfully make sudden big changes.

GNOME 3 has improved in the meantime. I still think the window switching, application launcher and top bar are inefficient and limiting, and it wastes screen space. So, I definitely won't be choosing GNOME 3. MATE reminded me that things have improved since GNOME 2, and I don't want that either.

Cinnamon seems good now. It seems to be a combination of the best of GNOME 2 and GNOME 3. Its web page may be unimpressive, but the software works well and has enough features. It seems significantly faster than KDE, and I'm forced to install a lot less stuff. Losing KDE 4 was annoying at first, but now it seems I'm switching to something even better.


I wonder what's wrong with this APC BE500U-CN Back-UPS ES 500?

$
0
0
I saw Cinnamon claiming that the UPS is empty (0%), which made me assume there was some bug in Linux. It even hibernated the PC even though AC power wasn't interrupted, which is definitely a bug. Then I double-checked via apcupsd in Linux, and then in Windows, with PowerChute Personal Edition 3.0.2 and CPUID HWMonitor 1.20.0. The UPS was definitely claiming it was empty. However, PowerChute said it was operating normally and charging.

HWMonitor provides the most interesting information. It constantly updates the battery voltage and levels, and keeps minimum and maximum values..The voltage was fluctuating from below 12 to above 13. That does not seem like proper charging. When I took the battery out, it was around 12.6. My first thought was that there was a bad capacitor causing excessive ripple and giving bad readings. This led me to open up the UPS:



I saw high ripple at the leftmost capacitor, near the red wiring fault light and the heat sinks. After replacing that 220µF 50V capacitor, ripple went down from 5V to 3V. I'm not sure that this helped though. When it started charging, HWMonitor reported voltage steadily rising toward 13.50V. It stayed stable for a while. Then it fluctuated going down to 11.54V even. Now, the voltage is stable again, around 13.26V, and percentage is rising.

The stability makes me think the fluctuations were the firmware interrupting charging and doing some discharge tests. Surely 11.54V is too low though. Maybe the battery is bad and the firmware isn't smart enough to report that. I saw it quickly go below 12V with a car headlight, so it probably is worn out.

CPUID HWMonitor 1.20 causes blue screens

$
0
0
32-bit Windows 7 is normally totally stable for me. Today I was running CPUID HWMonitor 1.20 to troubleshoot a UPS problem, and I got two blue screens. One was BAD_POOL_HEADER (19) and the other DRIVER_CORRUPTED_EXPOOL (c5). Both of these point to memory corruption.

HWMonitor is a nice utility which shows temperature, voltage and other measurements. It supports the motherboard, hard drive, graphics card and UPS. However, I've seen blue screens after using it in the past, and this experience further confirms that HWMonitor causes blue screens.

I just upgraded to version 1.27. I hope that version will work better.

Edit: Nope, it's not fixed. I didn't trust version 1.27, so wanted to restart after using it. I got another memory corruption crash on shutdown.

Sleep and wake notifications with systemd

$
0
0
After I upgraded to Ubuntu 15.04 Vivid Vervet, the Audacious plugin I used to control a display device I built had a problem. Functionality related to sleep and wake didn't work anymore. That's because UPower doesn't handle sleep and wake anymore. Notification events instead come from systemd-logind. In particular, it is the "PrepareForSleep" signal on the "org.freedesktop.login1.Manager" interface. When its argument is true, the system is preparing to go to sleep, and when it's false, the system is waking up. Here's the new code.

I still need to find a way to determine the last wake time. Formerly I was using the /var/log/pm-suspend.log modification time, but that is also now unavailable because systemd is handling it instead. If the plugin observes a wakeup, it gets the correct time from that, but when started it needs another method.

This illustrates a major difference between Windows and Linux. The Windows version of the plugin can still use the WM_POWERBROADCAST message, with parameters dating from Windows 2000. Linux is a moving target, and things will break unless you keep updating them. This probably also extends to Linux application APIs.

Gigabyte GA-P35-DS3R enables wake on any unicast packet by default

$
0
0
Recently I found that if I totally cut power to my computer (including standby power), booted to Linux and went into suspend, it would wake unexpectedly very soon. Booting into Windows would prevent this problem from happening until power is totally cut again. I suppose this problem existed before, but I never noticed it because I rarely fully cut power and I was using Linux less.

At first I thought this was a Linux bug, but actually, it the result of a crazy default setting for wake on LAN. By default, wake on unicast packet and magic packet are both enabled. If there was some network activity which caused ordinary unicast packets to arrive while the computer was sleeping, it woke up. That's why I found that with a minimal X setup using twm, the wakeups only happened if I was running a web browser.

This setting can be seen by running sudo ethtool eth0. Its output included:
        Supports Wake-on: pumbg
        Wake-on: ug

From the ethtool man page:
              u Wake on unicast messages
              g Wake on MagicPacket™

The solution was adding ethtool -s eth0 wol d to /etc/rc.local to disable wake on LAN. Then sudo ethtool eth0 would report Wake-on: d, which means "Disable (wake on nothing).". It's possible to also use g instead of d, which should only enable wake on magic packet.

The GA-P35-DS3R rev 1.0 motherboard F13 BIOS does not seem to have any options for changing wake on LAN settings, so this seems to be the only way to do it. I had already disabled wake on LAN in Windows via the Advanced settings in Device Manager. That setting persisted until standby power was cut.

It sure seemed like a Linux bug at first, so here's the Ubuntu bug I reported. Now I just wish Linux would tell me the wake reason. If something told me these wakeups were a result of wake on LAN, I would have wasted a lot less time on this.

Performance of the Em-DOSBox CPU interpreter

$
0
0
When I first got DOSBox to run in a web browser, performance was terrible. The problem was the CPU interpreter. A single function fetches, decodes and executes most x86 instructions. Most of the function consists of a big switch statement with many cases. It is big because there are many x86 instructions.

The first problem was Emscripten converting the switch statement into a long chain of else if comparisons. Actually, a switch statement was used, but in most cases it merely set a variable which was later tested via comparisons. Instruction decoding, which needs to be done for every instruction, changed from O(1) into O(n).

Emscripten could generate a much better switch statement with a patch. This made DOSBox run fast in Firefox, but it was much too slow to use in Chrome. When I profiled it, I saw a warning triangle by the CPU interpreter function, telling me it's not optimized because the switch statement is too big. There was already v8 bug filed about this issue.

I solved this problem by transforming the cases of the big switch statement into functions using extractfun.py. This reduces function size and allows a function pointer to be used instead of a switch statement. The process is somewhat convoluted because the switch statement is normally built using the preprocessor. First, preprocessor output files need to be produced. In order to get Automake to create them using proper dependencies, it needs to create a library which is otherwise unnecessary. Then the Python script parses the preprocessor files. It stores functions into a function store, removing duplicates and fixing name collisions. Finally, it creates header files which are used when building the final version of the CPU interpreters. Three CPU interpreters are processed this way: the simple, normal and prefetch cores.

Since then, the Emscripten bug has been fixed, I assume by the switch to Fastcomp. When Chrome started using TurboFan for asm.js, it could finally get good performance with an un-transformed CPU interpreter. This led me to check whether extractfun.py is still necessary.

Safari 8.0.6 and Internet Explorer 11 still get terrible performance without the transformation. Use of --llvm-opts '["-lowerswitch"]' doesn't seem to help. Looking at the JavaScript, I can confirm that it changes the big switch into a binary search, so this probably means the problem is due to the size or complexity of the function, and not just due to switch statements. I also experimented with the Emscripten outlining limit, with or without -lowerswitch. I assume that transforming switch cases into functions is a more efficient split than what's done by Emscripten outlining.
Viewing all 120 articles
Browse latest View live