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
- Compile foo.c into foo.o
- Link foo.o into foo
- Build a disk image called foo.po with ProDOS, Basic and foo.
- Start a test machine under Virtual ][ and insert the foo.po disk image
- 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:
- No target or “all” will compile and link
- Target of “image” will do #1 plus build the disk image
- 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:
- 2 bits per block = 2 bytes per column = 16 bytes per board = 32 bytes per level
- 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!