Build pipeline

I have my pipeline in a place where I can start using it. Not from the JetBrains tools, yet, like I wanted but at least in a place where I can get some “real” work done.

Again, I want to call out that this is not only work I’ve done. I’ve borrow heavily from others to get my persona build pipeline in place.  The old saying of “I can see further, for I stand on the shoulders on giants” is very fitting, but I more prefer “I can dig deeper, for I stand in the trenches of hackers.”  Seems more fitting.

Here is a quick demo of the build pipeline:

A few things to note with what I put together (which you will see further down in another example).  Specifying EXE= with make will do a few things if left alone.  For example, if you specify EXE=foo with the target of “test”, it will

  1. Compile foo.c into foo.o
  2. Link foo.o into foo
  3. Build a disk image called foo.po with ProDOS, Basic and foo.
  4. Start a test machine under Virtual ][ and insert the foo.po disk image
  5. Once it is booted it will BRUN foo

As this may and will not fit all case, I added a few extras.  You can specify SRCS= to be a list of files (including the base one), it will compile all those files and link all those files into the EXE value.  For example:

# make EXE=foo SRCS="foo.c bar.c fun.c"

Will compile foo.c, bar.c and fun.c into .o and then link them into foo.  Keep in mind you do need to include foo.c, you don’t get that for free.

As far as targets, there are a couple:

  1. No target or “all” will compile and link
  2. Target of “image” will do #1 plus build  the disk image
  3. Target of “test” will do #2 then boot the disk image and BRUN the executable.

I’ll put this all up on GitHub so anyone can use it if they want..

Testing some “real” code

Next, I wanted to test out some of the code I’ve been working on for my game.  Just some preliminary code to do some performance testing vs memory utilization.

I had two ideas of how I can represent a column of blocks for use in the game.  Given the following conditions:

  • A level needs two boards.  The initial layout of the board and the solution.
  • A board can have eight columns
  • A column can hold up to eight blocks
  • I wanted to be able to have at least three types of blocks

I came up with the following implementations:

  1. 2 bits per block = 2 bytes per column = 16 bytes per board = 32 bytes per level
  2. 1 byte per block = 8 bytes per column = 64 bytes per board = 128 bytes per level

128 bytes is not that much, but I wanted to consider both options.  The code for option #1 is much trickier than option #2 due to bit masking and shifting, but the space needed for #2 is four times the size.  So, the the unanswered question is which one is faster?  I predicted that that #2 would be faster due to all the funky bit math #1 has to do.

To test this, I coded up both implementations then ran them through it’s paces.  The code starts with a full column, takes all eight of the blocks out, then puts eight blocks back in.  It then does this 1000 times in a loop.

For the timing, I took some code from Bill Buckels I found on in a post on CSA2P and I converted it to a “library” that I could start a timer, get elapsed time and even do a “lap” timer.  It does require a No-Slot clock but luckily Virtual ][ can do that!  I’ll get that “library” up on GitHub, as well.

Here is a quick video showing the pipeline in action with multiple source files and the performance testing of the two implementations:

The winner in performance is the “string” version, which is the 1 byte per block with 1865 vs 2853 for the “bit” version.  FYI, the timer is in “centiseconds”, so it’s about 18.65s vs 28.53s or almost 10 seconds faster for the “string” version.

Using the “string” version has some other side benefits.  The code is cleaner and much more straight forward and it does allow me to expand the game to have a larger set of blocks, if I wanted.

Now to move on to implementing the boards, levels and the engine to hook them all together!

Tips welcome and strongly encouraged.

Based on tip from Quinn Dunki, I also wanted to explore Cadius as an alternative to AppleCommander.

Cadius is from BrutalDeluxe and is their ProDOS disk imaging utility, so I thought I’d get it installed and take it through it’s paces.

Manual install?  Umm, no thank you.

With as handy as HomeBrew is, not everything is in there.  As mentioned in the previous post, there is a set of formulae for Apple II utilities available here, which has a lot of great things in it.  One of the things NOT in there is Cadius.

I could have just installed Cadius using the instructions found on Cadius’ GitHib page, but what fun is there in that?  Time to learn to make a HomeBrew formula and make the (Apple II) world a little bit better.

I created the HomeBrew formula for it, which was very simple using the instructions found in the Formula Cookbook.  I have a pull request open against the HomeBrew Apple II repo to get it officially included.  If you want to use it before then, you can grab it from here.  One you have it you can install Cadius with:

Image in ProDOS’ self

Now that we have Cadius installed we need to create a disk image, that’s pretty easy:

Despite it being a valid ProDOS volume, it won’t boot like this. Similar to how DOS 3.3 disks, we need to do some extra things to this to make it bootable.  Namely, we need to put on BASIC.SYSTEM and PRODOS from another bootable ProDOS disk.

I was able to find the ProDOS system master on Call-A.P.P.L.E’s site here.  But, I realized it’s a .DSK in DOS order which Cadius will not read.  Fear not!  A quick search pointed me to a script by Paul Hagstrom called, oddly,  I downloaded that and fixed shebang line to use python and not python3 and converted the disk image (Thanks Paul!):

Now, I want as much space on my default ProDOS disk so I just want just the BASICs (see what I did there?) to get the disk bootable.  Let’s copy the needed files over to the new image that was just built:

And now for the boot:

So far, so good.

Back to the past

In the last post I added “helloworld” to a DOS 3.3 disk image with AppleCommander, booted it and ran the executable.  Let’s try that again, but using Cadius to put it on the new disk image and try the same thing.  This will prove that Cadius can be used in place of AppleCommander in my build pipeline.

And the pudding:



Cadius seems like a great alternative to AppleCommand IF you want to only work with ProDOS disks, but it was much more straightforward (detecting the AppleSingle format that we needed).

I think I’ll use it in my build pipeline going forward.  I guess I should stop playing around and should probably write some code for my game as well!