Anders Tornblad, web developer

I'm all about the web

Emulating ZX Spectrum graphics in JavaScript

TL;DR: I'm using EcmaScript 6 Proxy objects to keep track of dirty blocks in emulated ZX Spectrum video RAM. Try it out at or dive into the code by cloning or forking

Emulating 1982 video RAM in JavaScript

Animated GIF screenshot made using gifcreator.meAnimated GIF screenshot made using gifcreator.meIt's no secret that I have a sweet spot for the Sinclair ZX Spectrum. One of the things I was amazed by as an eight-year-old was the (then) incredible 256×192 pixel colour graphics. Using only 6.75 kilobytes of video RAM, the custom Ferranti ULA chip pieced together the video signal 50 (or 60) times per second.

Software emulation of the Ferranti ULA has been done a lot of times, but reinventing the wheel is a great way of learning new (or old) things, so I decided to make an attempt of my own.

JavaScript, CANVAS and Proxies, oh my!

First of all, I'm using a CANVAS element and the CanvasRenderingContext2D object to draw graphics in the browser's window. I'm also using a Uint8ClampedArray to store the 6912 bytes of raw video RAM. For a more detailed description of the memory layout, scroll down a little. Each byte of the array corresponds exactly to one byte of ZX Spectrum RAM, so changing the contents of a single byte should trigger a redrawing of at least a part of the canvas.

I decided to redraw the canvas in blocks of 8×8 pixels, because this is close to how the ZX Spectrum ULA worked. Changing any one of the 8 bitmap bytes inside a block, or its attribute byte, should mark that block as "dirty" and when the next animation frame comes along, all dirty blocks should be rerendered. Because of this, there is also a Uint8Array of length 728 (32×24) keeping track of dirty blocks, so that I don't have to redraw all blocks every frame.

Using a Proxy object, I'm able to use the array normally, while correctly marking dirty blocks as needed. Without a Proxy, I would have to expose a setter method for changing the RAM contents.

// Without a Proxy object: data.set(address, newValue); // With a Proxy object: data[address] = newValue;

The Uint8ClampedArray and Proxy construction looks like this:

var data = new Uint8ClampedArray(6912); var dataProxy = new Proxy(data, { "set" : function(target, property, value, receiver) { if (property >= 0 && property < 6912) { data[property] = value; var dirtBlockIndex; if (property >= 6144) { // The index is inside the attribute section dirtBlockIndex = property - 6144; } else { // The index is inside the bitmap section dirtBlockIndex = blockIndexFromOffset(property); } dirtyBlocks[dirtBlockIndex] = 1; return true; } // Not a numeric index inside the boundaries return false; } });

This creates a Proxy that, when written to, sets the value of the hidden array, calculates what block is changed, and markes that block as dirty, so that the next call to the renderer only redraws the dirty blocks. This speeds up the rendering process a lot.

The ZX.Spectrum.Bitmap object exposes the following public functions:

  • poke(address, value): Changes one byte of video RAM (valid adresses are within the 16384..23295 range)
  • peek(address): Reads one byte of video RAM
  • ink(value): Sets the current INK colour (0..7)
  • paper(value): Sets the current PAPER colour (0..7)
  • bright(value): Sets the current BRIGHT value (0..1)
  • flash(value): Sets the current FLASH colour (0..1)
  • cls(): Clears the screen using the current settings
  • plot(x, y): Sets one pixel, affecting the colour block
  • unplot(x, y): Clears one pixel, affecting the colour block
  • line(x1, y1, x2, y2): Draws a one pixel line, affecting colour blocks

Try it out

Go to and try it out for yourself. You can also clone or fork the code and play around. Pull requests are more than welcome!

Back to the 1980s

The ZX Spectrum was an amazing computer for its time. An advanced BASIC interpreter fit snugly into 16 kilobytes of ROM, and the 48 kilobytes of RAM included 6.75 kilobytes of graphics memory. Using BASIC commands like PLOT, INK and CIRCLE, you could write algorithms to draw things of beauty on the screen, but you had to look out for attribute clash.

The video RAM consisted of monochrome bitmap data containing one bit per pixel for a total of 256×192=49152 bits, fitting into 49152/8=6144 bytes, starting at address 16384. The order of pixel rows inside this memory area is a little strange, as rows are not placed linearly (each line of 256 pixels is not exactly 256 bits after the one above it). To calculate the screen address of the first pixel of a Y coordinate, you encode the address as follows:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 1 0 Y7 Y6 Y2 Y1 Y0 Y5 Y4 Y3 0 0 0 0 0

This effectively divided the screen vertically into three blocks of 256×64 pixels, within which it is easy to get to the next line of characters, and also easy to get to the next line within a character block by simply adding one to the high byte of the address, but calculating the screen position from a pixel coordinate is really convoluted.

Directly after that monochrome bitmap, at address 22528, was one attribute byte per 8×8 block, containing the colour values for the "ones" and "zeros" of the bitmap data. Each attribute byte is encoded like this:

7 6 5 4 3 2 1 0
F B P2 P1 P0 I2 I1 I0
  • F holds a one for FLASH mode, where INK and PAPER alternates every 32 frames
  • B holds a one for BRIGHT mode, where both INK and PAPER are a little brighter
  • P0..P2 holds a value between 0 and 7 for the PAPER colour, which is used for zeroes in the bitmap
  • I0..I2 holds a value between 0 and 7 for the INK colour, which is used for ones in the bitmap

Avoiding the "attribute clash" was tricky, and you had to really plan your artwork or your graphics algorithm to make sure that you only ever needed two distinct colours inside each 8×8 block of pixels. Artist Mark Schofield wrote an article in 2011, describing his process of planning and creating a piece of ZX Spectrum artwork.

If you are looking for more ZX Spectrum art, here are a couple of sites you might have a look at:

Using Source Maps with CSS

StackOverflow user Rob had a problem inspecting his SASS stylesheets after having them preprocessed by Codekit.

Having set the Output Style to "Compressed", the resulting CSS stylesheets were optimized and minified, making it almost impossible to trace the CSS back to the original SASS files.

Checking the Create a Source Map setting allowed him to help Google Chrome DevTools map the compiled CSS to the original SASS files, using a .map file, that the browser automatically uses. The principle of Source Maps is well known for JavaScript developers, but most people don't know that it is possible for CSS preprocessors too.

More information is available in the Codekit documentation for SASS.

FizzBuzz in CSS

One recurring complaint among experienced programmers is that there are lots of junior talent that could not even implement a simple FizzBuzz program. One blog article that started it off was Using FizzBuzz to Find Developers who Grok Coding, written in 2007 by Imran Ghory, and after Jeff Atwood wrote about it, literally hundreds of programmers wanted to prove their value by writing FizzBuzz solutions in every conceivable way and in every language available.

Just for fun, I tried writing a pure CSS solution, just like my pure CSS "Hello World" solution, but unfortunately, I couldn't. No matter how I try, I still have to add 100 P elements to the HTML document. But once that is done, the solution is really simple.

body { counter-reset: i } p { counter-increment: i; } p:before { content: counter(i) } p:nth-child(5n):before { content: '' } p:nth-child(3n):before { content: 'Fizz' } p:nth-child(5n):after { content: 'Buzz' }

This use of CSS is not as unorthodox as with Hello World, but it's still very convoluted. But then again, the FizzBuzz challenge is a pretty convoluted way of putting interviewees to the test.

Oh, and I made a pen for you.

Converting from Type to SqlDbType

StackOverflow user Simone Salvo asked how to do a smart conversion between .Net System.Type and System.Data.SqlDbType, which is not really a trivial task.

For my answer, I wrote the following somewhat naïve code:

public class SqlHelper { private static Dictionary<Type, SqlDbType> typeMap; // Create and populate the dictionary in the static constructor static SqlHelper() { typeMap = new Dictionary<Type, SqlDbType>(); typeMap[typeof(string)] = SqlDbType.NVarChar; typeMap[typeof(char[])] = SqlDbType.NVarChar; typeMap[typeof(byte)] = SqlDbType.TinyInt; typeMap[typeof(short)] = SqlDbType.SmallInt; typeMap[typeof(int)] = SqlDbType.Int; typeMap[typeof(long)] = SqlDbType.BigInt; typeMap[typeof(byte[])] = SqlDbType.Image; typeMap[typeof(bool)] = SqlDbType.Bit; typeMap[typeof(DateTime)] = SqlDbType.DateTime2; typeMap[typeof(DateTimeOffset)] = SqlDbType.DateTimeOffset; typeMap[typeof(decimal)] = SqlDbType.Money; typeMap[typeof(float)] = SqlDbType.Real; typeMap[typeof(double)] = SqlDbType.Float; typeMap[typeof(TimeSpan)] = SqlDbType.Time; /* ... and so on ... */ } // Non-generic argument-based method public static SqlDbType GetDbType(Type giveType) { if (typeMap.ContainsKey(giveType)) { return typeMap[giveType]; } throw new ArgumentException($"{giveType.FullName} is not a supported .NET class"); } // Generic version public static SqlDbType GetDbType<T>() { return GetDbType(typeof(T)); } }


The above code works fine in most cases, but comes with some problems:

  • How do you pick the correct SqlDbType value for strings? It depends on how you are using/storing that string in the database and in your application's business logic. The alternatives are:
    • Char: Fixed-length non-Unicode string of no more than 8 000 characters
    • NChar: Fixed-length Unicode string of no more than 8 000 characters
    • VarChar: Variable-length non-Unicode string of no more than 8 000 characters
    • NVarChar: Variable-length Unicode string of no more than 8 000 characters
    • Text: Non-Unicode stream of no more than 2 147 483 647 characters
    • NText: Unicode stream of no more than 1 073 741 823 characters
    • Xml: SQL Server native XML data type
  • How do you pick the correct value for blobs? There are a few alternatives there too:
    • Binary: Fixed-length stream of no more than 8 000 bytes
    • VarBinary: Variable-length stream of no more than 8 000 bytes
    • Image: Variable-length stream of no more than 2 147 483 647 bytes
  • Also for dates or timestamps there are a few different ways to go:
    • Binary: Fixed-length stream of no more than 8 000 bytes

The best thing would almost always be to let some ORM tool do the heavy lifting.

Finally got around to fixing Sparky

Back in 2010, the iPad was all the rage. The first really usable tablet device, sporting lightning-fast multitouch capabilities, that were even exposed as (then non-standard) HTML5 Web APIs for JavaScript developers to play with.

It wasn't always easy to keep up with the latest trends, and trying out multitouch experiments then required an iPad. So I wrote a touch event simulation tool, called addTouch. The principle was to use the mouse to add, manipulate and remove multiple touch points, dispatching touch events to the browser.

This made it possible to develop multitouch experiences and test them using an average desktop browser. I supported both Apple's touch events and the (now extinct) Mozilla touch events.

Sparky : just a demo app

Sparky in actionTo demonstrate what addTouch could do, I put together a simple demonstration app called Sparky. Its principle is very simple — put your fingers on the screen to create sparking lines that you can move around. This was in the really early days of HTML5 support, and I hadn't learned Canvas drawing yet, so my implementation uses a few <div> elements and some CSS transform magic.

This has worked fine for almost six years now. I just had to fix a small issue when Apple released the iPhone 4, which had a high-dpi ("Retina") display. There were a few versions of the iOS Safari browser that had bugs when it came to handling device pixels vs logical pixels. I had to do a lot of experimenting with this, and wrote a StackOverflow answer that is currently my third most up-voted one.

What started out as just a demo app for addTouch, now has a life of its own. After my latest complete blog remake, I have been keeping a close look at the IIS logs that I get from Azure. It turns out that Sparky still gets a few hundred visits per week from different incoming, which is nice, but it prompted me to do some much-needed spring cleaning.


The code was actually not too shabby, but some of it was really outdated. It still supported the old Mozilla touch events, and it used screen coordinates instead of local coordinates, which made it look pretty horrible in a non-fullscreen view, especially on the Android Chrome browser. That needed to change.

It was written in a certain style, specifically catered to my own old JavaScript minifier which I no longer use. Also, it polluted the global window object, which I never do anymore, unless I'm writing public APIs. That needed to change, too.

Other than that, it was just the small issue of estimating screen DPI, where I had used hard-coded values directly adapted for various iOS devices. That needed to be replaced with some more general-purpose code, and after a little head-scratching, I just decided to go with the same hard-coded value for all devices. At least for now.

The result is now live and kicking on, and the complete code is available in the lbrtw/sparky GitHub repository.

Next step

I will try to fix some of the issues with addTouch as well, but I'll save that exercise for later. It is not very useful anymore, because the major browsers and development environments have really good touch emulation built in.

Try it out:

"Hello, World!" in Pascal

How to do "Hello, World!" in Pascal.

program HelloWorld; begin WriteLn('Hello, World!'); end.

Pascal was one of the first computer languages I learned, back in the late 1980s and early 1990s. The Borland Turbo Pascal compiler was really fast, and I once actually took a university course in Computer Science, where we wrote code in Pascal on Macintosh computers. This was in 1996. A few years later, I had the opportunity to try Delphi 8 (Octane), which among other things had an immensly superior "Intellisense" solution.

I think I need to add Pascal definitions to my code formatting script...

For more "Hello, World!" examples, go to the Hello World category.

Finding the right namespace

StackOverflow user graham added a reference to a third-party DLL called ServiceProvider.dll, but couldn't figure out which using directive to use to access the types made available in that DLL.

Most times, the DLL is named after the default namespace, which would suggest that a simple using ServiceProvider; should help, but that didn't work. When using closed-source SDKs that you purchase licenses for from some company, it is pretty common to find that their namespaces are named after the company itself. In this case, the root of the namespace hierarchy was Avaya, after the company.

Object Browser screenshotObject Browser When you double-click the reference in the Solution Explorer, the Object Browser opens up with the double-clicked referenced assembly pre-selected. All you have to do then is to expand the selected row to see all namespaces included in the dll file.

403s for the Naughty List

As I mentioned in Complete Blog Remake, Part 2, there are lots of evil bots out there. They are relentless in their automated search for known exploits, and a lot of those target WordPress installations and plugins. Most of these go through the normal HTTP protocol, trying to find URLs that are routed to some badly written, exploitable PHP code. In my logs, I find thousands of calls to /xmlrpc.php, /wp-admin/admin-ajax.php, /wp-content/uploads/locate.php and others where there are current or older versions that expose known SQL injection or script injection exploits.

Because of how my routing is built, all of these requests are interpreted as possible article titles and sent to the ArticleController's Single(string postname) method, which searches for an article with a weird name, doesn't find it, and responds with a 404 page. The request gets logged by Azure, and when there are many bots (or just one unusually intense one), Azure alerts me of having many client errors in a short time period.

In the beginning, I used these logs to double-check that I hadn't missed any incoming links, but because of the huge amount of bots out there, the requests that I'm really interested in gets drowned out by the low signal-to-noise ratio.

Building the naughty list

Some requests could be people or crawlers (Google, Yahoo, Baidu, ...) just doing their job, following links that may or may not lead somewhere, so I don't want to blindly and automatically block the IP address of everyone making mistakes in typing or following a misspelled link. But if there are a few bad requests from the same IP address (say eight in 24 hours), I will block them.

Other requests are just blatant attempts at finding exploits. I will block the IP address of those calls instantly. The Single method makes use of the PageNotFound method of the base class, so the result is really straightforward:

public ActionResult Single(string postname) { if (postname.StartsWith("xmlrpc.php") || postname.Contains("wp-admin") || postname.Contains("wp-content/plugins")) { return PageNotFound(403); } /* Edited out: Code that searches for the requested article */ if (article == null) { return PageNotFound(); } }

The PageNotFound method of the base class isn't too complicated either. It calls the ApplicationData class to handle the list of suspicious or blocked IP addresses:

public ActionResult PageNotFound(int statusCode = 404) { if (applicationData.SuspectUserAddress(Request.UserHostAddress, statusCode == 403)) { return new HttpStatusCodeResult(403); } else { /* Edited out: Code that gives a nice 404 page */ } }

And here is finally some of the code that keeps track of suspicious IP addresses:

internal bool SuspectUserAddress(string address, bool confidentSuspicion) { // Is this address already blocked? Just return true. if (BlockedAddresses.Contains(address)) return true; // If I'm not sure yet, check some more rules if (!confidentSuspicion) { // How many times has this address acted suspiciously already? int count = SuspiciousRequestAddresses.Count(sra => sra == address); if (count >= 5) { // Do a reverse DNS lookup. Is it NOT a known nice crawler? if (!IsNiceCrawler(address)) { // Then this suspicion is a confident one! confidentSuspicion = true; } } } // Are we sure now? if (confidentSuspicion) { // Remove from list of suspicious requests SuspiciousRequestAddresses.RemoveWhere(sra => sra == address); // Add to list of blocked addresses BlockedAddresses.Add(address); return true; } else { // We are not sure... That means this request should be stored as a suspicious one SuspiciousRequestAddresses.Add(address); return false; } } private bool IsNiceCrawler(string address) { var parsed = IPAddress.Parse(address); var hostInfo = Dns.GetHostEntry(parsed); // Something like ($)|($)|($)|($) string validationRegex = ConfigurationManager.AppSettings["NiceCrawlersRegex"]; // Check all of hostInfo's aliases for one that matches the regex bool isNice = hostInfo.Aliases.Any( alias => Regex.IsMatch(alias, validationRegex, RegexOptions.IgnoreCase) ); return isNice; }

After doing this, the amount of 404s went down by a lot, but the 403 errors started rising. I checked a few times to see that the blocked requests are really exploit attempts, and I feel comfortable with this solution.

Also, I changed my Azure alerts to separate the different 4xx responses. I still want those unhandled 404s to generate an alert so that I can fix broken links. This works really well for me.

Complete blog remake, part 1
Complete blog remake, part 2
403s for the Naughty List (this part)

"Hello, World!" in ZX Spectrum machine code

How to do "Hello, World!" in ZX Spectrum machine code.

CHANOPEN equ 5633 PRINT equ 8252 ld a, 2 call CHANOPEN ld de, text ld bc, textend-text jp PRINT text defb 'Hello, World!' defb 13 textend equ $

This piece of code calls two functions in the original ZX Spectrum ROM. First it calls CHAN-OPEN which sets the current output channel to number 2 (normal screen output), and then it calls PRINT, which prints a string of characters to the selected channel. To print this on a ZX Printer, simply select channel 3 instead.

I think I need to add Z80 assembler definitions to my code formatting script...

For more "Hello, World!" examples, go to the Hello World category.