What not to write in haXe, Part II

I decided to have another go at writing some awe-inspiring haXe code again. This time, I picked up from where i left off – that was trying to get my infamous SCUMM interpreter working on additional platforms which haXe supports.

For reference, I concentrated on getting it to work on the neko platform.

To start off with, I took notice of a suggestion to simplify the import statements which littered the top of the source code. So instead of this:

#if flash9
import flash.display.Bitmap;
...
#else neko
import noflash.Bitmap;
...
#end

I consolidated everything into a single file which looked like this:

#if flash9
typedef Bitmap = flash.display.Bitmap;
...
#else neko
typedef ByteArray = noflash.ByteArray;
...
#end

So when I used “import hiscumm.Common”, I could now access all of the classes listed with little fuss!

Another change I made was to re-factor the way resources were loaded. Before, I just used flash 9’s ByteArray. However as there is no direct equivalent of this on the neko platform, I had to implement my own.

Thinking more, I determined that only a relatively small portion of my code actually needed to use all of the features of ByteArray, so instead I changed all of the IO code to use the neko api’s Input & Output classes.

Finally I made all 32bit integers Int32’s. Consequently, I had to re-implement the Int32 class for the flash platform, but all things considered it was the best solution.

Problems

As before, I ran into a fair share of problems. Most were minor, and others were solved when I upgraded from haXe 1.17 to 1.18. Here are some of the more notable ones I came across.

“No arrays larger than 115 elements”

I ended up finding a rather obvious solution to this problem which worked transparently with the other platforms. All one has to do is split up the troublesome array into several smaller arrays and then concatenate them together. e.g.

var longarray = [1,2,3].concat([4,5,6]).concat(7,8,9); // works

Problem solved.

“Beware of classes extending Int”

In an earlier implementation of my Int32 class, I had it extending Int. This turned out to be a fatal mistake, as when I tested out the code absolutely nothing worked.

The solution of course was just to not extend from Int.

“haxe.Timer does not have a constructor”

I kept getting a rather odd compile error. It seemed that no constructor was defined for the Timer class, which I used to run the game loop. This was very odd, as the API documentation didn’t state anything unusual about the Timer class on the neko platform.

However after checking out the code to the Timer, I soon came to realise the horrifying truth: the Timer class wasn’t implemented for the neko platform. Arrrgh! I got this far and now i’m stopped by something as simple as this?

Thankfully I figured out a rather obvious workaround. Instead of using the timer, I merely made a typical run-of-the-mill game loop. Problem solved.

while (true)
{
  onTime();
  neko.Sys.sleep(0.01);
}

The result

As the output below shows, the interpreter now actually runs on neko. Unfortunately there appears to be a rather nasty bug when decoding the room image. But then again i’ve not implemented any video code for the neko platform yet, so the usefulness of this is questionable to say the least.

$ neko test.n
NekoTest.hx:42: Engine init
SCUMM.hx:486: boot state
SPUTMResource.hx:308: Loading resource 1 from file 1, room 2 (SCRIPT)
SCUMM.hx:488: Started
SCUMM6.hx:1249: ARRAY = "" 
SCUMM6.hx:1249: ARRAY = "ScummC Paused !" 
SCUMM6.hx:1249: ARRAY = "Are you sure you want to quit ? (Y/N)Y" 
SCUMM6.hx:1249: ARRAY = "Are you sure you want to restart ? (Y/N)Y" 
SCUMM6.hx:1249: ARRAY = "Save it" 
SCUMM6.hx:1249: ARRAY = "Load it" 
SCUMM6.hx:1249: ARRAY = "Continue" 
SCUMM6.hx:1249: ARRAY = "Cancel" 
SCUMM6.hx:1249: ARRAY = "Quit" 
SCUMM6.hx:1249: ARRAY = "Ok" 
SCUMM6.hx:1249: ARRAY = "Saveing '%s'" 
SCUMM6.hx:1249: ARRAY = "Loading '%s'" 
SCUMM6.hx:1249: ARRAY = "ScummC test Menu" 
SCUMM6.hx:1249: ARRAY = "Save game" 
SCUMM6.hx:1249: ARRAY = "Load game" 
SCUMM6.hx:1249: ARRAY = "Game NOT saved" 
SCUMM6.hx:1249: ARRAY = "Game NOT loaded" 
SCUMM6.hx:1249: ARRAY = "Insert disk %c" 
SCUMM6.hx:1249: ARRAY = "You must enter a name" 
SCUMM6.hx:1249: ARRAY = "Insert your save disk" 
SCUMM6.hx:1249: ARRAY = "Failed to open %s (%c%d)" 
SCUMM6.hx:1249: ARRAY = "Read error on disk %c (%c%d)" 
SCUMM6.hx:788: 103, 645
SPUTMResource.hx:308: Loading resource 2 from file 1, room 2 (ROOM)
SPUTMRoom.hx:173: RMIM == RMIM
SPUTMImage.hx:109: smap size == 8
SPUTM.hx:1096: Internal exception, aborting! (state=SPUTM_RUNNING)
SPUTM.hx:1097: >>

As before, the hiscumm code is available for reference. Unlike last time however, the code is now hosted in a git repository so you can now see all the nitty gritty changes I have made to it. Great!

Click here to check it out!