mrxstudios

Dust Remastered

Reverse Engineering Dust: Uncovering Game Scripts

Dust: A Tale of the Wired West” is a game produced by Cyberflix in 1995. It was a game where the player had lots of conversations with colorful characters, collected inventory items and solved puzzles. There are simply too many branches in the game’s logic to uncover by simply playing it. So maybe there was a way of uncovering the game logic from the game files.

Dust Game Files

The Windows installation of Dust contains several executable files and game files of interest:

TypeDescription
ExecutablesDust.exe
DF.exe
MoviePlay.exe
CSTCast files containing the 3D characters and some game logic
FLTFlat files containing puzzle logic
MOVMovie files containing screen animations and still renders
PRPProp files containing 3D props that are placed throughout the game
PUPPuppet files containing characters dialogue, game logic and images of the characters
SETSet files containing game locations and game logic.
Types of Game Files

The game files are composed of a header and a set of blocks. I will go into greater detail about the file format of these game files at a later point in time, but all we need to know for now, is the following:

  • All game files except for movie files can contain Script Blocks
  • Puppet files also contain a list of dialogue lines that can be referenced from inside the Script Blocks

What does a Script Block look like?

All blocks in the Dust game files start with 4 bytes of block information: The block-ID and its size. Since we’re looking at the Windows version of the game files, all the data is stored in Little-Endian byte-order.
The Script Block consists of two sections:

  • Logic
  • Variable Lookup Table

Here’s an example of what we’ll be working with:

00000000 2f00 0000 8806 0000 0500 9805 0000 0000 |/_______________|
00000016 0500 9805 0000 0000 0300 9605 0000 0000 |________________|
00000032 0500 9405 0000 0000 0400 0100 0000 0000 |________________|
00000048 0600 0000 0000 0000 0600 0000 0000 0000 |________________|
00000064 a10f 0000 0000 0000 0500 7005 0000 0000 |__________p_____|
00000080 b20f 0000 0000 0000 b30f 0000 0000 0000 |________________|
00000096 0600 0100 0000 0000 a30f 0000 0000 0000 |________________|
00000112 0500 5205 0000 0000 0600 0100 0000 0000 |__R_____________|
00000128 a20f 0000 0000 0000 0500 3e05 0000 0000 |__________>_____|
00000144 b40f 0000 0000 0000 0500 3905 0000 0000 |__________9_____|
00000160 0600 0000 0000 0000 0600 0100 0000 0000 |________________|
00000176 092f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000192 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|
00000208 a60f 0000 0000 0000 0500 f904 0000 0000 |________________|
00000224 481f 0000 0000 0000 0400 0000 0000 0000 |H_______________|
00000240 0600 0200 0000 0000 0500 d904 0000 0000 |________________|
00000256 481f 0000 0000 0000 0400 0100 0000 0000 |H_______________|
00000272 0600 0200 0000 0000 0b2f 0000 0000 0000 |_________/______|
00000288 b20f 0000 0000 0000 0300 b404 0000 0000 |________________|
00000304 b30f 0000 0000 0000 0600 0200 0000 0000 |________________|
00000320 0b2f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000336 0300 9404 0000 0000 b30f 0000 0000 0000 |________________|
00000352 0600 0200 0000 0000 0b2f 0000 0000 0000 |_________/______|
00000368 b20f 0000 0000 0000 0300 7404 0000 0000 |__________t_____|
00000384 b30f 0000 0000 0000 0600 0200 0000 0000 |________________|
00000400 0b2f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000416 0300 5404 0000 0000 b30f 0000 0000 0000 |__T_____________|
00000432 0600 0100 0000 0000 a70f 0000 0000 0000 |________________|
00000448 0600 0100 0000 0000 0b2f 0000 0000 0000 |_________/______|
00000464 b20f 0000 0000 0000 0300 2404 0000 0000 |__________$_____|
00000480 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|
00000496 092f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000512 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|
00000528 a60f 0000 0000 0000 0500 ae03 0000 0000 |________________|
00000544 4b1f 0000 0000 0000 0400 0500 0000 0000 |K_______________|
00000560 0600 0200 0000 0000 0c2f 0000 0000 0000 |_________/______|
00000576 b20f 0000 0000 0000 0300 bc03 0000 0000 |________________|
00000592 b40f 0000 0000 0000 0400 6600 0000 0000 |__________f_____|
00000608 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|
00000624 a80f 0000 0000 0000 0600 0200 0000 0000 |________________|
00000640 0c2f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000656 0300 9003 0000 0000 b40f 0000 0000 0000 |________________|
00000672 0400 6600 0000 0000 b30f 0000 0000 0000 |__f_____________|
00000688 0600 0200 0000 0000 0c2f 0000 0000 0000 |_________/______|
00000704 b20f 0000 0000 0000 0300 7803 0000 0000 |__________x_____|
00000720 b40f 0000 0000 0000 0400 6500 0000 0000 |__________e_____|
00000736 b30f 0000 0000 0000 0600 0200 0000 0000 |________________|
00000752 0500 d602 0000 0000 481f 0000 0000 0000 |________H_______|
00000768 0500 c602 0000 0000 421f 0000 0000 0000 |________B_______|
00000784 0400 0500 0000 0000 0600 0100 0000 0000 |________________|
00000800 a70f 0000 0000 0000 0600 0100 0000 0000 |________________|
00000816 0c2f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000832 0300 1803 0000 0000 b40f 0000 0000 0000 |________________|
00000848 0400 6600 0000 0000 b30f 0000 0000 0000 |__f_____________|
00000864 0600 0100 0000 0000 0500 5a02 0000 0000 |__________Z_____|
00000880 481f 0000 0000 0000 3c4e 0000 0000 0000 |H_______<N______|
00000896 b20f 0000 0000 0000 421f 0000 0000 0000 |________B_______|
00000912 0400 0100 0000 0000 b30f 0000 0000 0000 |________________|
00000928 0600 0100 0000 0000 a90f 0000 0000 0000 |________________|
00000944 0500 1202 0000 0000 0600 0100 0000 0000 |________________|
00000960 ab0f 0000 0000 0000 421f 0000 0000 0000 |________B_______|
00000976 0400 0100 0000 0000 0600 0200 0000 0000 |________________|
00000992 a50f 0000 0000 0000 0600 0100 0000 0000 |________________|
00001008 ab0f 0000 0000 0000 0400 6500 0000 0000 |__________e_____|
00001024 0600 0200 0000 0000 0b2f 0000 0000 0000 |_________/______|
00001040 b20f 0000 0000 0000 0300 4402 0000 0000 |__________D_____|
00001056 b30f 0000 0000 0000 0600 0200 0000 0000 |________________|
00001072 f02e 0000 0000 0000 b20f 0000 0000 0000 |________________|
00001088 0300 6e01 0000 0000 b40f 0000 0000 0000 |__n_____________|
00001104 0500 1502 0000 0000 b20f 0000 0000 0000 |________________|
00001120 b30f 0000 0000 0000 b30f 0000 0000 0000 |________________|
00001136 0600 0200 0000 0000 ab3e 0000 0000 0000 |_________>______|
00001152 b20f 0000 0000 0000 0300 2601 0000 0000 |__________&_____|
00001168 b40f 0000 0000 0000 0300 da01 0000 0000 |________________|
00001184 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|
00001200 ab0f 0000 0000 0000 0400 6600 0000 0000 |__________f_____|
00001216 0600 0200 0000 0000 0b2f 0000 0000 0000 |_________/______|
00001232 b20f 0000 0000 0000 0300 a401 0000 0000 |________________|
00001248 b30f 0000 0000 0000 0600 0200 0000 0000 |________________|
00001264 863e 0000 0000 0000 b20f 0000 0000 0000 |_>______________|
00001280 0300 ae00 0000 0000 b40f 0000 0000 0000 |________________|
00001296 0300 7501 0000 0000 471f 0000 0000 0000 |__u_____G_______|
00001312 3a4e 0000 0000 0000 b20f 0000 0000 0000 |:N______________|
00001328 214e 0000 0000 0000 b20f 0000 0000 0000 |!N______________|
00001344 0400 0300 0000 0000 b30f 0000 0000 0000 |________________|
00001360 b30f 0000 0000 0000 b30f 0000 0000 0000 |________________|
00001376 0600 0100 0000 0000 aa0f 0000 0000 0000 |________________|
00001392 0600 0000 0000 0000 a40f 0000 0000 0000 |________________|
00001408 0600 0000 0000 0000 0600 0000 0000 0000 |________________|
00001424 0600 0000 0000 0000 0000 0000 0000 0000 |________________|
00001440 0750 5241 4952 4945 0557 4f4d 414e 054a |_PRAIRIE_WOMAN_J|
00001456 454e 4958 0344 4159 0972 756e 796f 7365 |ENIX_DAY_runyose|
00001472 6c66 0361 7267 0a70 6c61 7965 7263 6173 |lf_arg_playercas|
00001488 680a 6a65 6e69 7870 6861 7365 076a 656e |h_jenixphase_jen|
00001504 6978 2e35 076a 656e 6978 2e36 076a 656e |ix_5_jenix_6_jen|
00001520 6978 2e37 076a 656e 6978 2e38 076a 656e |ix_7_jenix_8_jen|
00001536 6978 2e39 1b4e 6f2c 2049 2064 6f6e 2774 |ix_9_No, I don’t|
00001552 2068 6176 6520 616e 7920 6d6f 6e65 792e | have any money.|
00001568 1f4e 6f2c 2049 2077 6f6e 2774 2067 6976 |_No, I won’t giv|
00001584 6520 796f 7520 616e 7920 6d6f 6e65 792e |e you any money.|
00001600 1759 6573 2c20 6865 7265 2069 7320 7468 |_Yes, here is th|
00001616 6520 6d6f 6e65 792e 034e 6f2e 086a 656e |e money._No._jen|
00001632 6978 2e31 300c 7075 7464 6f77 6e61 6374 |ix_10_putdownact|
00001648 6f72 0967 6176 656d 6f6e 6579 086a 656e |or_gavemoney_jen|
00001664 6978 2e31 310a 746f 776e 2e65 7874 7261 |ix_11_town_extra|

What does it all mean?

If we look at the Script Block, we can see that there is a pattern in the “Logic” part of the block.
The pattern consists of 8 bytes, where the first 4 bytes contain information and the second 4 bytes are always 00’s. This means that we can disregard the second half of the pattern.

If we look closer at the information bytes we can see that some values in the first two bytes of the information bytes are recurring more often than others. They are also the only ones that are followed by another 2 bytes of information, so they probably determine the meaning of the information that follows it. We’ll call the first two bytes the flag-bytes and the second two bytes the value-bytes:

NameFlag bytesValue bytes
A0x03000x????
B0x04000x????
C0x05000x????
D0x06000x0000 to 0x0200
X0x????0x0000

So we’ve defined flag bytes A-D for the most recurring and then X for the remaining flag bytes. Note that X does have recurring flag bytes as well.

Variables

At this point we have no idea what this all means. What we do know, is that we have a lot of variable names at the end of our script block. First let’s have a look at how these variables are constructed.

00001440 0750 5241 4952 4945 0557 4f4d 414e 054a |_PRAIRIE_WOMAN_J|

Each variable starts with a byte that defines the length of the string and is followed by a set of bytes in the ASCII range. In other words, they’re all Pascal Strings. For example, “PRAIRY” starts at offset 1440. The first byte 0x07 defines that the string is 7 characters long, followed by [‘P’,’R’,’A’,’I’,’R’,’I’,’E’]

Next, let’s see if we can find where these variables are referenced.
There aren’t any absolute references to the offsets of the strings. For example, “WOMAN” starts at offset 1448, but there is no value 0xA805 anywhere in the Script Block. So if it isn’t an absolute offset, maybe it’s a relative offset.

00000000 2f00 0000 8806 0000 0500 9805 0000 0000 |/_______________|
00000016 0500 9805 0000 0000 0300 9605 0000 0000 |________________|

If we take a look at the start of our Script Block, we have the following information in the first 32 bytes:

  • Block ID: 47 (0x2f00)
  • Block Size: 1672 bytes (0x8806)
  • Flag 5: 1432 (0x9805) at offset 8
  • Flag 5: 1432 (0x9805) at offset 16
  • Flag 3: 1430 (0x9605) at offset 24

If we assume the values of the flags are relative offsets, where do they land us?

8 + 1432 = 1440
16 + 1432 = 1448
24 + 1430 = 1454

Those are the offsets of our variables: PRAIRIE, WOMAN, JENIX
So we’ve figured out that flags A (3) and C (5) reference the variables at the bottom of the script.

Flag X

At this point we’ve uncovered part of the script, but it really doesn’t give us enough information to figure out what all the other flags mean. We can observe that some flags occur more often than others, such as 0xb20f and 0xb30f, but apart from that there really isn’t anything else to find.

When I was trying to decipher this, I got stuck for quite some time. The reason for this, is that I was missing a very important piece of the puzzle. This piece was locked away in one of the executables and I came across it while looking for human-readable strings.

While I was analyzing DF.exe in Ghidra, I came across a lookup table that contained what seemed like function names and programming operators.

Programming Code Lookup Table

Each line is a pointer to a string, followed by two bytes. These are the values of Flag X.
If we extract this lookup table from the binary, we can use it to replace these flags with the corresponding strings.

00001136 0600 0200 0000 0000 ab3e 0000 0000 0000 |_________>______|
00001152 b20f 0000 0000 0000 0300 2601 0000 0000 |__________&_____|
00001168 b40f 0000 0000 0000 0300 da01 0000 0000 |________________|
00001184 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|

If we replace flags A, C and X with what we now know, we get the following:

0600 0200: ?
ab3e 0000: actorowner
b20f 0000: (
0300 2601: JENIX
b40f 0000: ,
0300 da01: gavemoney
b30f 0000: )
0600 0100: ?
actorowner(JENIX, gavemoney)

Integer Values and Formatting

Now that we have uncovered the three most important flags of the script, maybe we can figure out what the other flags mean by filling in the blanks.

00000112 0500 5205 0000 0000 0600 0100 0000 0000 |__R_____________|
00000128 a20f 0000 0000 0000 0500 3e05 0000 0000 |__________>_____|
00000144 b40f 0000 0000 0000 0500 3905 0000 0000 |__________9_____|
00000160 0600 0000 0000 0000 0600 0100 0000 0000 |________________|
00000176 092f 0000 0000 0000 b20f 0000 0000 0000 |_/______________|
00000192 b30f 0000 0000 0000 0600 0100 0000 0000 |________________|
00000208 a60f 0000 0000 0000 0500 f904 0000 0000 |________________|
00000224 481f 0000 0000 0000 0400 0000 0000 0000 |H_______________|
00000240 0600 0200 0000 0000 0500 d904 0000 0000 |________________|
00000256 481f 0000 0000 0000 0400 0100 0000 0000 |H_______________|

We convert this to the following by filling in flags A,C and X:

arg 0600 0001 global playercash , jenixphase 0600 0001 puppetclear ( ) 0600 0000 0600 0001 if jenixphase = 0400 0000 0600 0002 jenixphase = 0400 0001 

If we look at flag B (0x0400), we quickly see that it’s an integer flag. The best example is the value 0 after “if jenixphase =

arg 0600 0001 global playercash , jenixphase 0600 0001 puppetclear ( ) 0600 0000 0600 0001 if jenixphase = 0 0600 0002 jenixphase = 1 

Now all we have left is flag D (0x0600). The flag value seems to increment and decrement as the script goes along. This becomes most apparent when looking at the larger script files in the game.
This flag is used to denote where the line breaks are, but also the amount of indentation (amount of tabs) that line should start with:

arg 
    global playercash , jenixphase 
    puppetclear ( ) 
    if jenixphase = 0 
        jenixphase = 1 

Parameters

Now we can completely print the script. However, there’s still one question unanswered:
What’s the difference between flag A (0x0300) and flag C (0x0500)?

I don’t have a definitive answer for this, but the main difference appears to be that flag A is used for variables that are function parameters and flag B is used for the rest. My best guess is that they used this for code coloring or bold/italic in their game engine to improve readability.

The Result

NameFlag bytesTypeDescription
A0x0300Parameter VariableReferences variable using a relative offset
B0x0400IntegerThe flag value should be interpreted as an integer
C0x0500VariableReferences variable using a relative offset
D0x0600IndentationDefines a new line and indents the following code by the flag value.
X0x????ScriptKey of the Script Lookup Table.
Uncovered flags
PRAIRIE WOMAN JENIX DAY 1 
code runyoself ( ) 
    local arg 
    global playercash , jenixphase 
    puppetclear ( ) 
    if jenixphase = 0 
        jenixphase = 1 
        puppetspeak ( jenix.5 ) 
        puppetspeak ( jenix.6 ) 
        puppetspeak ( jenix.7 ) 
        puppetspeak ( jenix.8 ) 
    endif 
    puppetspeak ( jenix.9 ) 
    puppetclear ( ) 
    if playercash < 5 
        puppetbevel ( No, I don't have any money. , 102 ) 
    else 
        puppetbevel ( No, I won't give you any money. , 102 ) 
        puppetbevel ( Yes, here is the money. , 101 ) 
        playercash = playercash - 5 
    endif 
    puppetbevel ( No. , 102 ) 
    arg = puppetevent ( - 1 ) 
    switch arg 
    case - 1 
        exitcode 
    case 101 
        puppetspeak ( jenix.10 ) 
        sendtoactor ( JENIX , putdownactor ( ) ) 
        actorowner ( JENIX , gavemoney ) 
    case 102 
        puppetspeak ( jenix.11 ) 
        actorstar ( JENIX , town.extra @ numtostring ( random ( 3 ) ) ) 
    endswitch 
endcode 

Dialogue Lines

If we look at the Puppet file this script was taken from, we can find all the dialogue of that character in Block 0:

jenix.2  :   They're yours!
jenix.3  :   No, thank you.
jenix.4  :   I couldn't...
jenix.5  :   Excuse me, stranger, excuse me.
jenix.6  :   I was just seeing if there were some old vittles and such.
jenix.8  :   Since Karl died, I don't know how I'm going to feed them.

Some of the variables that are referenced in our script by flag A are the identifiers of the dialogue lines from Block 0. We can use this to make the script even more readable:

PRAIRIE WOMAN JENIX DAY 1 
code runyoself ( ) 
    local arg 
    global playercash , jenixphase 
    puppetclear ( ) 
    if jenixphase = 0 
        jenixphase = 1 
        puppetspeak ( jenix.5: "Excuse me, stranger, excuse me." ) 
        puppetspeak ( jenix.6: "I was just seeing if there were some old vittles and such." ) 
        puppetspeak ( jenix.7: "In the slop pail...for my boys." ) 
        puppetspeak ( jenix.8: "Since Karl died, I don't know how I'm going to feed them." ) 
    endif 
    puppetspeak ( jenix.9: "Stranger, you got any money? Just five dollars, maybe?" ) 
    puppetclear ( ) 
    if playercash < 5 
        puppetbevel ( No, I don't have any money. , 102 ) 
    else 
        puppetbevel ( No, I won't give you any money. , 102 ) 
        puppetbevel ( Yes, here is the money. , 101 ) 
        playercash = playercash - 5 
    endif 
    puppetbevel ( No. , 102 ) 
    arg = puppetevent ( - 1 ) 
    switch arg 
    case - 1 
        exitcode 
    case 101 
        puppetspeak ( jenix.10: "Thank you, stranger. My boys, they thank you, too." ) 
        sendtoactor ( JENIX , putdownactor ( ) ) 
        actorowner ( JENIX , gavemoney ) 
    case 102 
        puppetspeak ( jenix.11: "Of course. I am sorry to trouble you." ) 
        actorstar ( JENIX , town.extra @ numtostring ( random ( 3 ) ) ) 
    endswitch 
endcode 

Final Thoughts

The moment that I put two and two together and figured out that the lookup table in the executable was connected to these script files, I knew I’d found something very important. I had uncovered all the game logic of Dust, which means that rebuilding the game had become viable.

After letting it sink in, I realized that not only was I now able to read the game logic, I could change it as well. Maybe I could uncover things that weren’t meant to be seen…

or maybe

just maybe

I could set my inner-child free and make a windmill-sized Leroy!

Published by

16 responses to “Reverse Engineering Dust: Uncovering Game Scripts”

  1. Jake Rutigliano Avatar
    Jake Rutigliano

    Wonderful! Do you think you can reverse-engineer Titanic Adventure Out of Time next?

    Like

    1. Thanks for your kind response. I was not planning on reverse-engineering “Titanic Adventure Out of Time”, mostly because I have my hands full with Dust for now. What a great game as well though!

      The good news is that Titanic was built on the DreamFactory game engine as well, so the files are structured in the same way. If it’s the scripts you’re after, you should be able to follow these same steps.

      Like

    2. Hi Jake, I just wanted to share with you that I’m currently posting all my progress of remastering Dust on facebook and instagram:
      https://www.facebook.com/dustremastered
      https://www.instagram.com/dustremastered

      Like

  2. What we really need is someone to figure out how to rip audio, Dust and Titanic had banging soundtracks

    Like

    1. Someone already managed to rip the soundtrack for Titanic. You can find it on youtube.
      As for Dust, it didn’t really have much music to it, mostly ambient noise with some guitar strums here and there.

      But I agree. However the audio codec is ADPCM, but it was implemented in their own way and using their own offset tables. Nearly impossible to decipher without the original code.

      Like

      1. I do not think accessing the audio is outside the realm of possibility. I found the TRK files in Titanic and the SND files in both games when opened in Audacity as raw audio using 8-bit PCM mono at 8000 Hz that you can clearly make out the sounds but there is a lot of noise on top of them so clearly there is some other kind of data in there as well because it sounds like a dial-up modem getting busy with a toaster in waterfall. Also if you attempt to do this as well I’d advise you don’t use headphones because it is VERY LOUD. The SND files from my analysis seem to follow the same block pattern as described above and I also found that PUP files also contain audio blocks. If the original code is absolutely necessary it should be possible, I would think, to locate the code responsible for decoding that data in the disassembler. I would maybe start by looking out for calls out to the waveOut* functions in winmm.dll ( https://docs.microsoft.com/en-us/windows/win32/api/mmeapi/nf-mmeapi-waveoutopen ) and working back to see where it would take me and starting my search there. This task might be much easier though once we know more about the game’s internal structure in memory.

        Like

      2. If it still helps you, you can extract the DUST sounds with my tool “DFET”, at least those which are in the .PUP and .SND files. The decompression algorithm is for all file formats the same from version 1.0 up to version 4.0 (maybe even beyond). The code to decompress it can be found in my github. Look for the methode DFfile::audioDecoder in libs/DFfile/DFfile.cpp.
        You will also find methodes that glue the containers together and write it as WAVE files. The 2 different image decompression algorithms may be also useful for your projects.

        Link to DFET:
        https://github.com/M3tox/DFET

        Liked by 1 person

      3. Hey MeToX,

        So good to see so many different initiatives going at the same time.
        Great work on the audio!!
        I’m very impressed. I managed to figure it out too, but I needed some help to get there from the original developers.

        My tools are nowhere near as polished as yours though.

        Thanks for reaching out! Especially a big thanks for referencing my blog. I’m completely humbled! This way everyone will find each other’s work one way or another.

        I’ll test your tool out when I have some time.

        Like

    2. Hi there, I just wanted to share with you that I’m currently posting all my progress of remastering Dust on facebook and instagram:
      https://www.facebook.com/dustremastered
      https://www.instagram.com/dustremastered

      Like

  3. This is so incredibly cool. Fantastic work!

    I’m really hoping you’re still working on this project. Dust was always a huge favorite of mine growing up.

    Like

    1. I really appreciate that! I’m still working hard on it.
      I’ll see if I can write about some more progress I made in the meantime.

      Like

    2. Hi Greg, I just wanted to share with you that I’m currently posting all my progress of remastering Dust on facebook and instagram:
      https://www.facebook.com/dustremastered
      https://www.instagram.com/dustremastered

      Like

  4. Just came across your blog! As a big lover of Dust and Titanic, this is awesome work. Would love an update to your project 🙂

    Like

    1. Thanks so much for reaching out! I have some time off work towards the end of this month, so I’ll have some more time to share some progress. Perhaps I can do a small blog about either the Reverse Engineering of the old game, or the Remastering of the new one. Any preference?

      Like

      1. I would love to know more about the remastering of the new game 😊

        Liked by 1 person

      2. Hi there, I just wanted to share with you that I’m currently posting all my progress of remastering Dust on facebook and instagram:
        https://www.facebook.com/dustremastered
        https://www.instagram.com/dustremastered

        Like

Leave a comment

Design a site like this with WordPress.com
Get started