mgran's ars technica

Saturday, July 14, 2007

Open Sound System (OSS) 4.0 goes GPLv2

"The Open Sound System (OSS) is one of the first sound systems for Linux, predating ALSA, but in the last 10 years it's stalled in version 3.8 (the last public GPL version) and it's being replaced by ALSA as the sound system of choice in Linux. ALSA is a Linux-only solution, while OSS works in a range of Unixes. Now, OSS 4.0 is out under a GPLv2 license, with a number of advanced features over ALSA, like its new dynamic VMIXing capabilities, low-latency kernel modules, simple API and many other features. This release seems to be important enough to shake the foundations of the current Unix desktop sound systems, specially in Linux."

Labels: , , , , ,

Wednesday, July 11, 2007

Font Rasterization Issues in Current Systems

The AGG Project has a font rasterization discussion on what went wrong with font rasterization in Windows, Linux, MacOS and Adobe and suggesting enhancements: "I'll start with a tough statement. Microsoft played a dirty trick on the world. Windows XP way of text rendering has zero taste and zero engineering culture. Their text looks sharp and eye catching but wrong. They use too aggressive font hinting. Microsoft hinting not only distorts the letter-forms, but accumulates a huge error along the text line. While Microsoft uses their aggressive hinting there will be no higher than 100 DPI resolutions, period. Text in Adobe Acrobat looks much more consistent and very close to what you have on a printer. Text in MS Word looks sharper, but ugly in general. I do not like Apple rendering either. To me it really looks too blurry. It looks like they use some kind of a strange auto-hinting that blurs horizontal strokes, but does not offer any advantages. In fact, their hinting looks lousy. This is really why windows people do not like Safari. The Windows way of text rendering is bad, the Linux way is much worse. The apparent problem is very visible "dirty blots" in the round corners introduced by anti-aliasing. In general, we can say that the oblique strokes look heavier than the stems, which gives you an impression of dirt. It's possible to improve the corners with gamma correction when rendering, but still, it's impossible to achieve perfect consistency. What can we do? The amazing thing is there is no rocket science! Nothing to patent! All information is publicly available and/or deducible from what we see. Only unhinted text, with its natural blurriness, accurate glyph advance values calculated at a high resolution."" See also the Render Model for X.

Labels:

Monday, August 21, 2006

Downloading Binary Streams with Javascript XMLHttpRequest

(or How to do Binary Ajax)

I've been fiddling around trying to download a binary stream using the object XmlHttpRequest (XHR) of Javascript in Mozilla Firefox.

What I wanted was to be able to create a byte array containing the original bytes of the downloaded binary file. This mechanism would be used to implement a ROM loader, without modifying the original binary file (e.g. changing its binary encoding to some form of text at the server), because I wanted to reuse legacy binary files already stored in third-party servers which I couldn't modify.

After looking at developer.mozilla.org, many online docs (e.g. here and here), IANA's docs, checking hundreds of technical blogs, googling around etc, I wasn't able to find any example (or even an implied acknowledgement) that the object XmlHttpRequest could be used to fetch a binary file into a byte array. Instead, the general consensus is that any attempt at doing that is destined to result in a garbled binary stream and the 'problematic' binary download should never, ever be tried with XmlHttpRequest.

I decided to set out to find out a way to use this object to download any generic binary file. The problem I faced is that a usual Javascript code, in Firefox, for downloading a text file, would by default use a unicode-derived encoding and it would (1) eat up bytes in the binary stream because they would correspond to a single unicode-like character or symply ignore some of them because they were undefined in the character encoding; (2) unpredictably map some bytes into others (it seems the most affected range in the unicode charsets is between values 128-160, but in the default charset the affected range is 128-255). The result using the code below to fetch a binary file is a mess.


//fetches text/plain file synchronously. Do NOT use for binary files!
load_url = function(url) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
var req = new XMLHttpRequest();
req.open('GET',url,false);
req.send(null);
if (req.status != 200) return '';
return req.responseText;
}

After looking in the XMLHttpRequest documentation I realized I could force the HTTP request header to ask for a specific MimeType. In principle, the only necessary thing would be to force Javascript to interpret the received string characters as a constant 8-bit-length encoding, such as ASCII, as can be seen in the code below. A UTF-8 or any other variable-length encoding such as the default one should be avoided for the reasons above.


//should fetch binary files synchronously. But it DOESN'T work.
load_url = function(url) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
var req = new XMLHttpRequest();
req.open('GET',url,false);
req.overrideMimeType('text/plain; charset=us-ascii');
req.send(null);
if (req.status != 200) return '';
return req.responseText;
}


However, I discovered that even though now the resulting string length was correct, the underlying US-ASCII charset conversion of Javascript still mapped bytes in the range 128-160 to garbage.
I tried many (I really mean many) other 8-bit-length charsets without success. It seems that all available charsets reserved part of their range to code undefined and control characters in a fierce purposeful attempt to overcome my initial objective.

Then, after greping around, I found the file firefox/res/charsetalias.properties, which includes all accepted charsets in Firefox. After trying some extra charsets whose aliases were not available in any other source, I FINALLY found a simple charset that correctly instructed Javascript to map an identity between the received stream bytes and the characters returned by the string responseText. The code below is the correct one to download a byte stream in Javascript:


//fetches BINARY FILES synchronously using XMLHttpRequest
load_url = function(url) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
var req = new XMLHttpRequest();
req.open('GET',url,false);
//XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
req.overrideMimeType('text/plain; charset=x-user-defined');
req.send(null);
if (req.status != 200) return '';
return req.responseText;
}


After reviewing some UNICODE documents, it seems that the explanation is that the charset x-user-defined uses the UNICODE Private Area 0xF700-0xF7ff to map its range.

Now you just access the bytes in the received binary stream as you would access characters in the returned string:


var filestream = load_url(url);
var abyte = filestream.charCodeAt(x) & 0xff;


where x is the offset (i.e. position) of the byte in the returned binary file stream. The valid range for x is from 0 up to filestream.length-1.

If you use the code above, please leave the comment about the author (me) for recognition of the many hours of labor to find this out. Please bear in mind that even though it worked for me and I'm making this code available in the hope it may help you too, I do not take any responsibility for any problems this code may cause to you or your project!

Labels: , , , , , , ,

Wednesday, August 02, 2006

The Story of the Windows Registry

The Windows Registry is basically a file system optimized for handling small files. Each such file is equivalent to a few-bytes entry (the name-value pair) in a config (.ini) file. It is a 20-year-old '80s ad-hoc abstraction devised for the original Windows for DOS to replace the config (.ini) files. (that's why Microsoft recommends at most 2048 bytes in each registry entry.)

At that time, storing one config entry per file directly on FAT-FS was an unjustifiable waste of FAT16 entries -- there was a maximum number of 65536 cluster entries in FAT16, which would be rapidly exhausted into configuration entries since each file requires at least one FAT cluster -- and waste of disk space of (at the time) expensive disks -- because each cluster was at least 512 bytes, and in 2GB disks it was around 32KB (so each name-value pair would require at *least* 32KB!).

And storing entry files inside .ini files is also not the best solution, since setting up individual attributes such as ACLs, or management of the entries, becomes a nightmare, is not fast for parsing or granular enough for quick edition.

Therefore, building a file system (REG-FS?) optimized for storing such name-value entries was crucial. Too bad it was an ad-hoc solution, but it's somewhat justifiable if you think that at the time Microsoft wasn't so big and therefore probably didn't do enough research in new file systems (or operating systems :).

Today, the registry should simply be wiped off from Windows. The original requirements do not hold anymore. Wasting an extra 100MB for storing name-value entries directly on NTFS or FAT32 is not too bad nowadays. Indeed, NTFS is somewhat optimized for accessing small files together with ACLs (see MFT). And accessing them using the cosy file API is priceless. [It would be an interesting project to write a replacement registry api which would just map directly to some NTFS folder.]

Justifying the registry in terms of aggregating 'user' and 'system' configuration in different files is not sustainable. This is equivalent of having eg. two different NTFS directory hierarchies 'user' and 'system', containing each the respective name-value entries as small files. Copying, creating and managing the registry this way would be so much easier. No more that bloated registry API or unimportable .REG files. Registries could be shared by just mounting a SMB share. Very easy to manage centrally. NTFS is able to report file access events just as in registry events.

However, there are better solutions that that to store configuration files. One possible solution nowadays (both for Windows and for Linux) is Reiser4 FS . It was specially developed for this purpose. From their abstract: " Reiser4 uses dancing trees, which obsolete the balanced tree algorithms used in databases (see farther down). This makes Reiser4 more space efficient than other filesystems because we squish small files together rather than wasting space due to block alignment like they do. It also means that Reiser4 scales better than any other filesystem. Do you want a million files in a directory, and want to create them fast? No problem."

A note on NTFS: "Inside the Windows NT File System" the book is written by Helen Custer, NTFS is architected by Tom Miller with contributions by Gary Kimura, Brian Andrew, and David Goebel, Microsoft Press, 1994, an easy to read little book, they fundamentally disagree with me on adding serialization of I/O not requested by the application programmer, and I note that the performance penalty they pay for their decision is high, especially compared with ext2fs. Their FS design is perhaps optimal for floppies and other hardware eject media beyond OS control. A less serialized higher performance log structured architecture is described in [Rosenblum and Ousterhout]. That said, Microsoft is to be commended for recognizing the importance of attempting to optimize for small files, and leading the OS designer effort to integrate small objects into the file name space. This book is notable for not referencing the work of persons not working for Microsoft, or providing any form of proper attribution to previous authors such as [Rosenblum and Ousterhout]. Though perhaps they really didn't read any of the literature and it explains why theirs is the worst performing filesystem in the industry...."

I'd appreciate any comments to improve the article.

Labels: , , , , , ,

Monday, July 10, 2006

Simple http proxy scripts in bash

I'm using these two http proxy scripts to access web pages using my proxy with very good results.

They are specially useful if you are trying to set up a "GIT_PROXY_COMMAND=[shellscript]" shell variable or somehow accessing web pages by shell script.

#! /bin/bash

(read -s a; read -s b;echo "CONNECT $1:$2 HTTP/1.0";echo;echo $a; echo $b) | socket [myproxyip] [myproxyport]

#! /bin/bash

(echo "CONNECT $1:$2 HTTP/1.0"; echo; cat) | socket [myproxyip] [myproxyport] | (read a; read a; cat)

You may need to install the debian package socket (apt-get install socket).

In case you need a more general http proxy, able to handle any TCP request such as SMTP, telnet, ssh etc, you can have a look at transconnect, a transparent network proxy over HTTP.

Labels: , , , , , ,

Friday, July 07, 2006

ECS A929 Laptop Disassembly and Power Plug Replacement

After some years of use, I 've had a problem with my old ECS i-Buddie A929 Laptop that seems to be common enough: its internal power supply connector (the DC-in jack) melted and one of the three pins remained in the external power plug, which was destroyed as well by the extreme heat (see below). This problem is due to the use, by the manufacturer, of a defective laptop internal connector jack which is not strong enough to endure normal use conditions and over time it cracks and overheats until it melts down suddenly when the ground pin loosens out and it is held in place only by a tiny fraction of the original metallic anchor (at this point, the resistance builds up and it works as a heater resistance in overdrive, sparking and heating up until it melts). Luckily, my house didn't burn down to the ground.

Since I wasn't willing to pay half the price of the laptop (the warranty had already expired) by asking ECS to fix the problem they were responsible for in the first place, I opened the laptop up and fixed it myself. Since it seems that lots of people are having a similar problem, I
decided to post some pictures and hints to guide those who might want to solve the problem by themselves too. Be warned, though, that opening this laptop is like walking through a maze: there are several dozens of hidden screws that seem to have been purposefully located to hinder the owner in maintaining it. It took me hours to find out how to open it up, solder the broken pin back, and put it back together. I hope you will fare better with the pictures below to guide you. Also, even though I'm posting this list in the hope it can be useful to you, I do not take any responsibility for any damage it may cause to you or someone else you work for!

Although I disassembled an A929, I believe that its close relatives A928, A980 etc will have quite similar blueprints.

You are gonna need a solder and a soldering iron. I bought mine at ebay for only 2.80 pounds the soldering iron and 1.00 pound the silver solder. I chose silver solder (4% silver, 96% tin) because it's supposed to have more resistance to thermal cycles than the usual cheap lead solder that the manufacturer probably used.

At any time, do not touch the electronics on any board. Handle the boards by pulling and pushing them using their edges only, specially the mainboard and the RAM. This will minimize any chances that you burn them up with your undrained static electricity. Keep in mind you will be dealing with electric equipment, therefore do not do this close to any liquids, taps or damp locations. Be thoroughly isolated from the ground using shoes etc.
  1. Remove the power cable from the laptop. Make sure you are not charged with static electricity (momentarily touch something connected to the ground before starting and avoid walking on carpet, using jumpers and touching your hair).
  2. Turn the laptop upside down.
    Remove every screw you see. Remove the harddisk, cdrom, and memory. Below the memory you'll find a metallic plate. Remove it to find out hidden screws (see magnified picture). Remove them.
  3. Now remove the keyboard.
    Use a flat screwdriver and force gently up the edge under the space key, the left bottom (below the left alt key) and the right bottom of the keyboard (below the arrows). In the exact places you'll find out tiny ledges around the bottom edge of the keyboard. Use them as support points to lever the keyboard up. Pull the keyboard cable from the connector below it.
  4. Remove the plastic hinge caps between the laptop and the lcd display. Pop them out gently using a flat screwdriver.
  5. Without the hinge caps, you can now remove the plastic skin over the power button on the top.
    Similarly to the keyboard, there will be tiny ledges around it that you can use as support to pop it up gently. Remove the screws on the electronic board holding the power button beneath the plastic skin. This will expose some more hidden screws below the board to be removed too.
  6. Beneath the keyboard you'll find a metallic plate. Remove it and there will be more hidden screws that you must remove.
  7. Remove the screws on the hinges between the laptop and lcd. Now you can remove the last screw on the outer case, that inaccessible one beneath the lcd bottom.
  8. Ok, now we are able to pop the upper plastic skin up. Do it gently, because there will be a thin cable connecting the mousepad to a connector beneath the keyboard. Pull the cable from the connector before raising the upper plastic skin up completely.
  9. Fold the plastic skin over the lcd, as a book page.
  10. Now, you'll find another large metallic plate.
    Remove every screw connecting it to the board below. There is a hidden screw below a small circular white plastic label. Pull the metallic plate out. Put this large metallic plate aside the laptop for a moment.
  11. Remove the screws of the speakers.
  12. Remove the screws on the back of the laptop, those around the serial and parallel ports.
  13. There will be half a dozen screws to remove from the mainboard, to free it from the lower plastic case of the laptop.
  14. Finally, fold the mainboard over the lcd as if it was a book page.
    You'll then be able to see your power supply connector from the inside, in the most inaccessible possible place of the entire laptop.
    My connector was melted from the inside, and it was possible to see a hole in the place where the pin was supposed to be.
  15. For you to be enough space to solder the pin back in, you'll need to remove still some more half a dozen of screws holding the mainboard to the metallic plate that is close to the connector.
    This plate is the one over the SiS740 chip with a fan in the middle.
  16. Clean up the connector
    and the pin
    with some metallic sponge to remove the oxidized metal from the burnout. Put the pin back on the hole in the correct position (at this point, I plugged in my new external plug to make sure that the pin would remain straight during soldering). Shed a drop or two of silver solder on the back of the connector, over the place that melted down, so that the pin is back firmly in contact with the outer metallic triangular layer of the connector. [***Make sure NOT to short circuit this pin (ground) with either of the two ones (both positive) that lay below it - or you will see a large fume consuming your laptop when you turn it back on...***] I used a small piece of paper to isolate this pin from the two below it during soldering. After soldering, use a multimeter or something similar to certify that no short-circuit between this pin the the two below is present.
  17. Let's test it. Put back the metallic plate of (15) - put back its screws - and flip back the mainboard to its original position without putting back its screws. Put the RAM back in its connector in the mainboard. Plug in the external adapter plug in the connector you just soldered and turn the power on for some five seconds or so. You should hear the fans turning on and see the BIOS booting the computer on the lcd, even without keyboard and harddisk. If so, turn it off, remove the power cable and go to (18). If you don't hear the fans or see the lcd showing the BIOS booting the computer, turn it off immediately and make sure you plugged the RAM correctly (the RAM must be completely inserted with the two white arms fitted snugly around it) and use a multimeter to verify if the pins are receiving the correct +20/-20 dc voltage. Test it again. If it still doesn't work, you'll need to find by yourself what is wrong. It might be a range of things, from burned ram or electronics up to short circuits somewhere. At this point, it should just work (tm) if the problem was just the pin.
  18. Put back the screws on the mainboard (do you remember which ones? :) and its back (the serial/parallel ports). Put the large metallic plate you set aside over it and screw it back. Fold back the upper plastic case of the laptop, connect the mouse, put the screws beneath the keyboard place, the small metallic plate over it, and finally connect it put back the keyboard. Screw back the power button electronic board. Put back its plastic skin. Screw back the lcd hinges. Put back their plastic caps. Test again if the laptop will turn on and see if the BIOS shows up. If so, turn the laptop upside down and finally put back its cdrom and harddisk. Remove the RAM and put back the screws, small metallic plate over them, the RAM over it, and the other small metallic plate over it, closing everything with the plastic cap. That's it! Use the half dozen or so remaining screws you didn't find a place for them as a souvenir.
As you can see,

my external plug was completed melted as well in the great meltdown of my A929. I needed to buy a new one to replace it. You can buy new ones on the american and german ebays (1.99 pound). If you need a specific vendor, I can suggest the one I used. Just drop me a comment.

Labels: , , , , , ,