Keeping it SMPL

By | January 9, 2016

#FOR1,100($n,I will not...)SkoolKit 5.1 has been released. Even though it goes without saying, I will say that copies of 5.1 are available from the download page (as usual), the Python Package Index (as usual), and the Ubuntu PPA (as usual).

Before we embark on a tour of the new features in this release, allow me to divulge a small piece of previously unrevealed history. Back in January 2012 – between 2.4 and 2.4.1 in SkoolKit time, if that’s how you prefer to measure dates – I added an item to my SkoolKit TODO list about making it possible to define a new skool macro in terms of existing skool macros without writing any Python code. At the time, it was just an idea that I hadn’t really fleshed out. And it stayed that way until fairly recently – between 5.0 and 5.1 in SkoolKit time, as it happens – when I finally decided on a scheme that would bring the idea to fruition.

Enter 5.1 with the @replace directive, the ability to evaluate arithmetic expressions in macro parameters, and seven new skool macros: #(), #EVAL, #FOR, #FOREACH, #IF, #MAP and #PEEK. Together they constitute the Skool Macro Programming Language – SMPL (pronounced ‘simple’, I’ve just decided) for short. With them you can effectively define new macros that are shorthand for complex forms or combinations of the classic skool macros, or that fill in gaps in their capabilities.

For example, let’s look at the good old #UDG macro. It’s fine as far as it goes, but one thing it has lacked all these years is the ability to specify an address from which to collect the desired attribute byte; instead we’ve had to hard code the attribute value into the #UDG macro’s parameter string. Now, though, with the advent of the #PEEK macro, that has changed. Suppose the game we’re disassembling arranges tiles in groups of nine bytes: the attribute byte first, followed by the eight graphic bytes. Then we could create an image of the tile at 30000 like this:

#UDG(30001,#PEEK30000)

Which is nice, but perhaps not a great improvement over hard coding the attribute value. Now suppose that we want to create images of the tiles at 30009, 30018 and so on:

#UDG(30001,#PEEK30000)
#UDG(30010,#PEEK30009)
#UDG(30019,#PEEK30018)
...

This is getting tiresome. However, the nascent SMPL programmer within you should be noticing a pattern to these macros; they are all of the form:

#UDG(addr+1,#PEEKaddr)

where addr is the address of the tile’s attribute byte. Having identified the pattern, we can now embody it in a @replace directive, which replaces one regular expression with another:

@replace=/#udg\i/#UDG(\1+1,#PEEK\1)

With this directive in place, we can now create images of the tiles with the appropriate attribute values thus:

#udg30000
#udg30009
#udg30018
...

Which, I hope you will agree, is actually starting to look somewhat handy. But still, typing out all these #udg macros is a pain when there are 20 of them (say). So let’s use a #FOR loop instead to cut down on the typing:

#FOR30000,30171,9||n|#UDG(n+1,#PEEKn)||

If you’re still not convinced of the merits of SMPL, try this control file snippet on a snapshot of Hungry Horace:

@ 28663 replace=/#maze\i/#UDGARRAY#(32#FOR(\1,\1+767)||n|;#tile||)
@ 28663 replace=/#tile/(31735+8*#PEEKn),#MAP(#PEEKn)(61,2:60,3:56)
b 28663 Maze layouts
N 28663 #maze28663(maze2)
N 29431 #maze29431(maze1)
N 30199 #maze30199(maze3)
N 30967 #maze30967(maze4)
i 31815

Now take a look at the data block at 28663, with its correctly coloured images of the mazes in the game, each one composed of 32×24 tiles. All without a single line of custom Python code in a SkoolKit extension module.

Well, I’ve done my best to showcase SMPL in this brief introduction. The rest is now up to you.

For details of the other (boring by comparison) changes in 5.1, see the changelog. But after that, go forth and define new macros.

5 thoughts on “Keeping it SMPL

  1. Michiel

    Hi Richard, great job on developing Skoolkit! I started to disassemble a few of my old favourites. In doing so I use SMPL for a specific way of extracting sprites with different hights and widths. Is there a SMPLer way of doing things? In ‘Indiana Jones and the last crusade’ I use this FOREACH (so the code is reusable and relatively easily adjustable):
    ; #FOREACH(28160)||n|#UDGARRAY12,5,4,12;n-(n+11);(n+96)-(n+107);(n+(96*2))-(n+((96*2)+11));(n+(96*3))-(n+((96*3)+11));(n+(96*4))-(n+((96*4)+11));(n+(96*5))-(n+((96*5)+11));(n+(96*6))-(n+((96*6)+11)){0,0,384,208}(LOKn)||
    It gives a nice Indiana cracking his whip, fully stretched (hence the width of 12 UDG’s).
    Does a macro exist in which widht and hight are easily adjustable and the hight doesn’t need to be a multiple of 8?

  2. SkoolKid Post author

    Hi Michiel

    Yes, your #UDGARRAY macro could be written more simply (though not SMPLy!) as:

    #UDGARRAY12,5,4,12;28160-28747-1-96{0,0,384,208}(LOK28160)

    Assuming the other graphics you’re interested in are laid out in an analagous way, an image of width ‘w’ tiles and height ‘h’ tiles at address ‘a’ can be created with a #UDGARRAY macro of the form:

    #UDGARRAYa,5,4,w;a-(a+w*h*8-1)-1-(w*8)...

    So you could define a #sprite macro for this pattern using @replace:

    @replace=/#sprite\i,\i,\i/#UDGARRAY\2,5,4,\2;\1-(\1+\2*\3*8-1)-1-(\2*8)

    And then the image of width 12 and height 7 at 28160 could be built thus:

    #sprite28160,12,7{0,0,384,208}(LOK28160)

    Hope that works and helps!

  3. Michiel

    Hi Richard, your suggestions were spot on! I took it one step further:
    @replace=/#sprite\i,\i,\i,\i/#UDGARRAY\2,5,4,\2;\1-(\1+\2*\3*8-1)-1-(\2*8){height=(\4*4)}(LOK\1)
    And the image with automated crop and name thus:
    #sprite28160,12,7,52
    Since this is used in over a hundred times and varieties in the skool file, thanks for pointing this out to me!

  4. SkoolKid Post author

    Good stuff. Glad to be of help.

    Maybe we’ll see one of your disassemblies in the links gallery some day? 🙂

  5. Michiel

    Certainly. I’ll finish my first complete disassembly of Space Raiders (by Psion) in a couple of weeks. As soon as I do, I’ll post a link here in the comments. It has served me well to build my disassembling skills.
    After that, Indiana Jones. This disassembly has been on my bucket list since 1989, so I HAVE to get it out of my system!

Leave a Reply

Your email address will not be published. Required fields are marked *