DirPlayer: A Shockwave emulator for modern browsers

Oliver Brown
— This upcoming video may not be available to view yet.

I recently posted about Flashpoint Archive, a way to play old Shockwave (and other) content. I have just discovered another option DirPlayer.

What is DirPlayer?

DirPlayer is written in Rust and compiled to WebAssembly and is available two different ways:

  • As an extension from the Chrome Web Store. This is useful for visiting any old or archived sites and just automatically loading the Shockwave content.

  • As a single JS polyfill. This allows people hosting the content on pages they can still edit to make their Shockwave content available to any modern browser.

Current status

At time of writing, version 0.3, has just been released. I’ve tried Supremacy in it. There is good news, and bad news.

The good news is the game launches. The fonts don’t work properly, and some buttons do not have colours making them hard to read, but you can actually start a game. Sadly, there is then a runtime error.

But I’ve decided to add Supremacy back on to the site in its original location and included the DirPlayer polyfill, which I hope to keep updated as development continues.

Supremacy - Shockwave game

Oliver Brown
— This upcoming video may not be available to view yet.

I started programming from a young age. One of the earliest programming projects I worked on that I was pleased with was a version of Risk called “Supremacy”.

Interacting with this video is done so under the Terms of Service of YouTube
View this video directly on YouTube

Shockwave was a technology created by Macromedia as a sort of companion/competitor/successor to the then ubiquitous Flash1.

Back in late 2000, I managed to get access to Macromedia Director1, the authoring software, and started playing around with it.

This was back when I was learning much of my programming from books (there was less available on the internet then). So I bought “Advanced Lingo for Games” by Gary Rosenzweig (Lingo being a bespoke programming language created just for Director).

Both Director and Advanced Lingo for Games are available on the Internet Archive now.

Supremacy is heavily based on the “Strategy Game” code sample included with that book. So much so, that the “Copyright © 2001 Oliver Brown” with no attribution makes me cringe a little now. So now is as good a time as any to thank Gary Rosenzweig for writing the book (and the code). I did eventually take it further, but that is for another post.

I made the game available on a website called “Shocklive!” on March 14, 2001 (and apparently released an update on March 18 with “no known bugs and better AI”).

Shocklive! as of May 17, 2001.

Today, the game has been submitted to the Flashpoint Archive and should be available soon.

Random trivia

Since it has been almost 25 years since I worked on the game, my memory has gaps. But I do still have the source code, so here are some things I can either remember or have worked out.

The name

Early in development I called it “Domination”, which is why the main file for the game is called dom.dcr.

Risk mechanics

It really is a bare bones version of Risk (mostly because it was designed as a programming tutorial and at best as a jumping off point to do more).

It has the original 42 countries from Risk, and uses the base rule: reinforcements equal to a third of your country count. It does not have continent bonuses however. This makes it much harder to snowball and as a result games tend to take longer (see the video).

It also does not use dice - every battle just gives attackers and defenders an even chance to win. This, combined with the fact that it also has no cards further lengthens games.

The computer player names

The default computer players are named after famous fictional AIs:

  • Deep Thought - The super computer from the Hitchhiker’s Guide to the Galaxy that determined the Answer to The Ultimate Question of Life, the Universe, and Everything was 42, and which went on to design an even more powerful computer, the Earth.
  • Orac - A sophisticated artificial intelligence from the British sci-fi TV series Blake’s 7.
  • Ziggy - The super hybrid computer from the sci-fi TV show Quantum Leap that runs Project Quantum Leap.
  • Zen - The master control computer of the Liberator, also from Blake’s 7.
  • Hal - The artificial intelligence and main antagonist in 2001: A Space Odyssey.
  • K-9 - The robot dog that was a companion in Doctor Who.

Title background

The background image is a Vietnamese girl holding an AK-47. I believe I sourced it from somewhere implying the girl was undergoing training to be part of some militia or military.

I still have the original copy and when I did a reverse image search I found it, with the description:

a Vietnamese high school girl practises taking aim with an AK-47 assault rifle during military training for students in Hanoi September 8 2000 high school and university students in communist ruled Vietnam take part in such training every year as part of a national defence programme"

Fonts

The main title font is Romulan Eagle. It sounds Star Trek based (which definitely makes sense with my interests at the time) but I honestly cannot remember anything about it. I have no idea where I found it. Possibly from the internet, possibly from a CD (CDs full of fonts were popular then).

The body font is Tahoma a standard Microsoft font which was apparently the standard screen font for Windows XP.

Also included in the project for some reason is Monaco, a font by Apple that was standard on Macs at the time. Which is a bit odd since I was using Windows at home and Acorn Computers at school.

Galaxia branding

Some time after the initial release, I added the message “Brought to you by Galaxia”. Galaxia is another game I developed (from which I got the online name I’ve been using ever since - GalaxiaGuy). I was working on a new version of Galaxia (which I tried a few times) when I first started this blog. The old Galaxia posts are still available.

Life on this blog

In fact, the game was available for a while directly on this blog. Sadly, this is no longer the case.

Screenshots

Some in game screenshots:

Opening in the project in Macromedia Director on a Windows XP VM:


  1. All the links say “Adobe”. It was Macromedia at the time. It shall live forever in my heart as “Macromedia”. ↩︎ ↩︎

Flashpoint Archive

Oliver Brown
— This upcoming video may not be available to view yet.

I’ve just found out about Flashpoint Archive, an application for playing old content created using Flash, as well as other obsolete browser technologies.

Interacting with this video is done so under the Terms of Service of YouTube
View this video directly on YouTube

The core functionality is provided by sandboxed versions of the plugins that run the content, a proxy server for games that need to believe they are run over the internet, and a launcher allowing you to browse and launch content - all wrapped up in a neat package.

And for the true archivists, there is a version that embeds all the content for download that, at the time of writing, is 2.28TB.

I’m interested in this for a couple of reasons.

Firstly, the preservation of history. I would like everything we create as a culture to remain available in some way (which is why I also support the Wayback Machine and the Internet Archive). I’m also of the right age that much of this was some of the most popular content available on the internet when I started using it.

But also, I myself have some stuff I’ve produced that is hard to access in modern browsers. Specifically, some Shockwave and Silverlight games.

So, for the near future I’m going to do what I can to get my games added to the archive.

Accessibility in UK retail mobile apps

Oliver Brown
— This upcoming video may not be available to view yet.

I have slowly been getting more interested in the accessibility of mobile apps. This has partly been driven by finding out just how many options there are to improve accessibility of apps, both for users and developers, and realising that many developers don’t know they exist. And, even when they are known about, there isn’t always much information about how to use them well.

To make this a bit more robust, I installed a bunch of UK shopping apps just to see what the current state of accessibility was and the results were… disappointing.

In fact, the issues I found were bad enough and widespread enough that I decided to write a series of posts going over some of the issues and explaining methods to improve them.

Testing details

The following is based on an iPhone 15 running iOS 18.5. Despite being an Android user myself, I have far more experience developing for iOS. I want to approach this with the goal of improving things and not just dunking on apps with shortcomings. For iOS I can give more concrete advice about how to make things better.

I also limited myself to just browsing around the app. I did not create an account, I did not attempt to purchase.

Summary of common issues

Before I get into the weeds of specific problems in specific apps (and hopefully how to improve them), I have a summary of common issues that were present in most apps.

Lack of large text support

Users can change the size of the text on their device, and many do. In fact this is probably the most used accessibility feature with somewhere between 20% and 30% of users selecting a larger text size.

For iOS developers, this feature is called dynamic type. For many system controls it is enabled automatically.

For custom controls, it is is enabled automatically in SwiftUI (but can be disabled), but has to be explicitly enabled in UIKit.

Cross platform frameworks vary. Xamarin did not support it and getting to work was tricky. MAUI supports it by default.

For the apps I tried:

  • Several had no support at all for large text. They are likely using UIKit for everything, or a wrapped web view.
  • Most had sporadic support for large text. The specific places suggest it was accidental. This could be some system controls without a custom font, or SwiftUI controls embedded in UIKit.
  • A few had broken support - some screens mostly unusable. Likely using SwiftUI with automatic support but with no testing.

Voiceover

iOS has a built-in screen reader, VoiceOver. Standard controls are well supported automatically, and simple layouts should just work. Any even slightly complex app will require additional work to make sure things have the correct labels, ordering is sensible, and element grouping makes sense.

Sheets and popups

Several apps had problems with modal displays that were not actually modal. That is, a full screen popup that still let you interact with UI in the background (that you couldn’t even see).

Worst of all, most of these examples were during the app onboarding making it the first thing a user would interact with.

Most also had smaller popups or menus that didn’t focus properly when they appeared.

Ordering

A key feature of VoiceOver is sequential navigation. You can always navigate to “next” and “previous” elements under the assumption that user may not be able to see the screen at all. For this to work the content has to be sensible order.

Simple cases will just work, but grid layouts may not work automatically, and overlapping elements will almost certainly have some undesirable ordering.

Every app had at least one screen that handled this very badly. They also had screens that were just about usable but not pleasant.

Grouping

By default every element that has text or is interactive will be treated as a separate element to VoiceOver. This isn’t always desirable.

One common example is multiple text elements (often with different formatting) intended to be read in one go are split up. Every app had at least one example of this, with some handling badly in many places.

Another one that is a bit more subjective is handling long lists. Imagine a list (or commonly a grid) of products with a title, a price, a brand name, a star rating, a “like” button, and an image. If each of those is an individual element, it takes very many “next” swipes to get through items. Nearly every app had this problem.

Labels

Text content will be labeled automatically, but images need to have labels added manually. If one isn’t specified, iOS will often read out the file name of the image which is often nonsensical.

Every app had at least one example of this. Most also had at least one label that obviously added but not useful (for example an image just labeled “Promotional banner”).

Other interaction methods

As well as VoiceOver, there are a few more ways to interact with an app that largely depend on the same works as above - good naming, ordering, and grouping.

Switch control

With switch control interaction can be limited to a small number of switches. This is not something I have tried very much, but it fails without good item ordering.

Voice control

Select elements by saying “Tap X”. Unintuitively this is quite resilient to poor element naming since you can see* the labels and it has built-in support for disambiguation. What does cause problems is insufficient grouping. Most of the apps had areas with too many individual items in close proximity that were hard to select.

* I used it while I could see. This can be combined with VoiceOver by a user who cannot see. In which case all the difficulties of VoiceOver also apply.

Other minor points

Invert

iOS has a smart invert option that inverts all the colors. Developers should annotate photographic imagery to be not inverted, but most of the apps did not.

Bold

Users can choose to make all text bold. This will be supported automatically if using system fonts, but not if using custom fonts. None of the apps supported this properly, with only a few controls (likely using system fonts) appearing bold.

How to check if a number is divisible by 14,669

Oliver Brown
— This upcoming video may not be available to view yet.

The method

Here is an easy way to determine if a number is divisible by 14,669.

First, multiply the last digit by 1,467. Then, take that number and add it to the remaining digits as if they were a number that is one digit shorter. Then repeat the process until the number is “clearly” divisible by 14,669 or not. This will match whether the original number is divisible by 14,669.

Okay, so maybe not that easy.

There is also another rule for handling numbers greater than a billion that can be speed things up (check the video below).

At least one reputable mathematician calls these the “Oliver Brown tests”.

An example

Firstly, here are the first 10 multiples of 14,669:

Lets consider the number 3,681,919.

Number Last digit × 1,467 Remaining digits Result
3,681,919 13,203 368,191 381,394
381,394 5,868 38,139 44,007

44,007 = 14,669 × 3

therefore 3,681,919 is also divisible by 14,669.

But why

Matt Parker of Standup Maths wrote a Python script to generate divisibility rules for numbers up to 30,000. The above is one of them.

Interacting with this video is done so under the Terms of Service of YouTube
View this video directly on YouTube

Stop killing games European Citizens' Initiative

Oliver Brown
— This upcoming video may not be available to view yet.

Stop Killing Games

The people behind StopKillingGames.com have launched a European Citizens’ Initiative as part of their cause.

This is essentially a petition that if sufficiently supported, would require an official response from the European Commission. Based on the reasons in my previous post, I urge all EU citizens to sign.

At the time of writing, it has reached 355,503 of the 1,000,000 required signatures, and a minimum threshold in 6 out of 7 countries. It must reach its target by 31 July 2025.

Stop killing games

Oliver Brown
— This upcoming video may not be available to view yet.

You have missed your chance to play The Crew

A new campaign has started to try and preserve video games that become unplayable when the developer and/or publisher no longer wishes to support them.

This post is mostly a collection of random commentary on games that I have tried to order as coherently as possible.

For a more succinct description of the problem and what you can do to support, visit StopKillingGames.com.

Growing up with games

This is a topic that I feel strongly about. I grew up playing video games. The first games I remember playing were on a Commodore 64. The first that were my own were on a Nintendo GameBoy and Sega Master System. Since then I’ve owned many consoles and computers. I’ve owned a few that were essentially “before my time” like an Atari 2600. In fact I first got into programming on a Sinclair ZX Spectrum.

This means I have a lot of memories playing video games, and for most of that time I knew that those games would remain playable indefinitely. The reality of hardware degradation means that for practical purposes most people would have to resort to emulation, but in theory someone who owned the original game would always be able to play it.

That is no longer the case for many modern games.

New games

There are some games that fundamentally require server resources to run. For some those those can be run by individuals - many early MMOs like Ultima Online have private servers for instance. Others like EVE Online might never be reasonable to run locally. And despite the fact that I would like these to remain playable indefinitely, these are not really the games that concern me the most.

Live service games

The games for which this is a problem is live service games, especially ones with a significant single player component. I think if a practical solution is to be found, then the “single player” aspect is going to have to be important - after all a mostly multiplayer live service game is pretty close to an MMO.

One sticking point is disagreement between the people running the game and the people playing the game what kind of game it is. Both Diablo III* and Diablo IV require an online connection to play, and the latter certainly adds quite a lot of content that only really works online. But a large number of players, including myself, only play it solo. But I have also played both Star Trek Online and Elder Scrolls Online (which are definitely MMOs) predominantly alone.

* Interestingly, Diablo III on console did not require an online connection. The result was hacked save files, which meant choosing to play with strangers online was awkward. But playing alone was fine.

Ubisoft and The Crew

This issue has come to prominence recently after Ubisoft decided to shut down The Crew. This is not a game I have played but it sounds like it falls to the sticking point I mention above. A lot of the game is based around being online and playing with others, but not all of it.

Ubisoft are making the opinion of the problem quite clear though, apparently taking things a step further and revoking digital licenses. This seems like a crazy move - I can imagine people making well reasoned arguments about companies not having to put resources into supporting games, but that doesn’t really hold any water when considering removing all access to people with digital games.

What to do

StopKillingGames.com is probably the bast place to go for information on how you can help. I would also suggest being as selective as you are able in the developers and publishers you support. For me, I personally spend more time playing single player indie games which generally don’t have this problem (being the digital license issue).

My games

For my own games (currently this means Tic-Tac-Toe Collection but I intend it to apply to anything else I ever make) I will always follow the principle of not requiring an online connection unnecessarily. That means that core functionality should not require it at all, and any features that do require it should not impact the rest of the game.

I have accidentally proven this a few times by managing online resources badly and allowing services to go offline. The game continued to work fine.

Exploring the generic math interfaces and fixed-point arithmetic in .NET

Oliver Brown
— This upcoming video may not be available to view yet.

In .NET 7 (previewed in .NET 6) a series of new interfaces were introduced to make work with mathematical operations easier.

.NET has had generics almost forever allowing you to write algorithms that work with many different types, but this hasn’t been possible for basic maths until this was introduced.

The main reason this has been done now is for machine learning and AI implementations where the classic computing tradeoff of speed vs. space appears - if you’re dealing with very large arrays of numbers, maybe you want to switch from a 64 bit double to 32 bit float (or even the newly introduced 16 bit half).

The in-progress implementation of my expanded Elo rating system is based on this for that reason.

Fixed-point arithmetic

There is another reason to use the interfaces though - perhaps you want a completely different implementation of the basic mathematical operations. One example would be fixed-point arithmetic instead of floating-point arithmetic.

The biggest reason to do this is because floating-point arithmetic is not, in practice, deterministic.

More about floating-point arithmetic determinism

This is a subtle topic. Any specific IEE 754 floating point operation is deterministic for the same inputs. But those inputs include various settings that might change unexpectedly, and things like reordering of operations will give you different results due to rounding.

And it is even worse in .NET (ironically) because of its portable nature. Your code could be JIT compiled completely out of your control on many different processor architectures.

Here are some more resources about it:

There have been a few implementations of fixed-point arithmetic in .NET:

That last one is fairly recent (it targets .NET 6) and is MIT licensed, so I decided to see if I could modify it to support the generic math interfaces.

GamesWithGravitas.FixMath

The (still in-progress) result is available here in GitHub.

It takes the F32 and F64 types from FixPointCS and implements the following interfaces:

  • INumber
  • IBinaryNumber
  • ISignedNumber
  • IRootFunctions
  • ITrigonometricFunction

Most of the work is forwarding to the existing implementations. Some of the things that I had to actually write code for:

Formatting and parsing

There are a bunch of methods relating to converting to and from strings. My implementation uses double as an intermediate type. I guess these have the chance to not be deterministic but for the things I’d use it for it would not matter.

TryConvertFrom… and TryConvertTo…

These methods are used to convert between these types and others. They come in three versions: Checked, Truncating and Saturating. I have currently implemented all three to do the same thing.

Mapominoes - or learning to hate islands even more than when playing Plague Inc.

Oliver Brown
— This upcoming video may not be available to view yet.
As an Amazon Associate I earn from qualifying purchases. See here for more information.

A while ago I bought Mapominoes Europe on a whim, and I’m now having to fight the urge to buy its many variations/expansions.

As the title suggests it is broadly based on dominoes, but instead of placing tiles by the numbers they have in common, it is based on countries with shared borders. Also unlike dominoes the cards are played not in a line but in a grid, and all neighbours have to be compatible.

The mechanics are simple enough to pick up and the game is quite suitable for children - I’m having fun playing with my six year old. It does hide some surprising depth though.

All the cards are dealt between the players and the goal is to be the first to play all your cards. Every player also starts with a pair of transit cards which can be played as stand-ins for either a sea (which are listed on the cards just like countries) or as another country. You get an extra turn if you can play a card bordering more than one card, and miss a turn if you are forced to draw another transit card because you can’t go.

There are several versions of the game, some of which are compatible with each other and can be combined into a larger game. The compatibles ones are:

A finished game of Europe and Asia & Australasia

There are also two standalone games:

After getting the Europe set I also got the Asia & Australasia set. Despite it taking up a lot of space, playing with those two was a lot of fun. Trying to play game with more than two would be challenging I think (although specifically in the case of those two it is helped by both sets containing Russia and Turkey).

Elo rating for ad hoc teams

Oliver Brown
— This upcoming video may not be available to view yet.

One final feature my expanded Elo rating needs (or at least the last I can think of) is the ability to deal with ad hoc teams.

By “ad hoc teams”, I mean teams of individual players with their own ratings that are on the same team for a specific game, but don’t generally stay as a team (established teams that always play together should be treated as their own “players” with their own rating).

This is not a common requirement, but the specific use case I had was an office ping pong table. Some times people would play singles and some times they would play doubles, but with no really established teams.

Necessary features

Firstly, the two key ratings operations need to work:

  • Estimate the result of an unplayed game
  • Updating ratings after an actual result

And all the existing features should be supported:

  • Two or more teams
  • Unfair games
  • Ties

Additionally, it should support teams of arbitrary (and mixed) sizes, including teams of size one. This brings us to one of our first less-obvious requirements - since this is expanding an existing system, it should be compatible with the existing system where it overlaps. So the following additional requirement makes sense:

  • Teams of one should give the same result as just using individuals

Simple solution

Just like with unfair games in which an adjusted rating is calculated first, and then used in the rest of the algorithm, and adjusted rating should be calculated for a team. This would trivially allow all the existing features to just work.

The most obvious way to calculate such a rating would be a simple arithmetic mean of all the players. This would definitely support our key requirement, but would it produce meaningful results?

At this point I think simplicity has to win out over sophistication. The most general solution would allow players to be weighted on each team (perhaps different roles in a team have different impacts on the result) but I think those situations are more likely to be handled with a per team rating.