arcfusion art, code, and games
Makin' Games from Scratch - Sat October 31, 2015

Makin’ Games from scratch

After spending a few months writing a few games for OneGameAMonth challenge, I found myself lacking the time to flesh out a game that I wanted to make. Instead, it felt as if I was rushing to get anything done in a month. (Life has a way of a stealing time from you at every corner.)

I was using a combination of love2d (based on lua) and several third-party libraries to load tile maps, handle collisions, sprite animations, etc. This sped up development, but most of the framework had to be written from scratch (and was done for the first game in January). However, after completing a few games, my motivation waned. I wasn’t making the types of games I wanted to play.

I had a lot of fun the first month writing the underlying systems for entities (aka in-game units). I added config scripts to make the framework a bit more reusable. I stubbed out a basic UI for showing entity health and screen transitions.

This was exciting because there was a lot of creative freedom.

As a transition towards achieving my goals, I decided to fallback on my own technology – which I’ve been refining as a hobby for years.

Let’s take a step back for a history lesson – this all began before the OneGameAMonth games I wrote.

In 2007, I made a Tetris-clone called 0x04. The base code for this formed the foundation of this tech. This was fairly basic and used SDL and CEGUI. CEGUI was huge – much larger than the rest of the game combined.

The next project I used it for was a 2D platformer called Isocarbon. For this, I added Box2D support and libvorbis+libtheora for audio and video playback. I dropped CEGUI and wrote my own UI system. After making a rough prototype, I didn’t find it fun (and didn’t make an effort to explore it). Motivation quickly waned and I stopped working on it.

After the course of several years I made multiple prototypes without anything sticking. Here are a couple samples:

While no complete games were written, I have been writing tools and evolving this game foundation code as a learning exercise. Thus far, two very useful tools have emerged from this:

blacksmith, A data-driven asset compilation utility which came about from a realization that eventually all assets would need to be cooked in some way. It made no sense to me to put this logic in the engine code – as I wanted that fairly minimal and fast. So I created a tool which leveraged command line tools to perform the work.

pegasus, A custom project generation tool similar to CMake, Premake, and Waf. It has evolved out of several re-writes. When building complex projects, I felt time was wasted hooking up various dependencies and fighting with multiple build systems to get cross platform builds. Something used Makefiles on one platform and had visual studio projects on another; another used CMake to generate platform-specific projects and none of them integrated well with one another.

These tools have been the backbone of the main project I’m working on, gemini. It aims to be my own home grown game technology. Developing gemini continues to push these tools as well as needs change.

I find it much more entertaining and relaxing than trying to cobble something together in Unity or Unreal with little to no say in those architectural choices.

Of course, these days I’m focusing on developing a game with it so it can properly evolve. I hope to make more posts detailing the architectural choices. I know I make sweeping changes at times and switch directions – but that’s the beauty of this remaining a hobby project and writing your own tech.

2014 New Years Hat - Wed January 15, 2014

2014 New Years Hat

I was really busy at the end of December, but wanted to make something for New Years Eve. I whipped up this New Years Hat in a couple days and most of that was because I have little experience sewing and eventually started soldering wires in.

This uses an Adafruit NeoPixel Ring (16), Arduino LilyPad, 3.7v 850mAh LiPo battery, and a hat I bought a couple years ago. I also used a MakerBot Replicator 2X to print a battery holder out of ABS, because I didn’t want to attempt sewing a battery pouch. I wanted an excuse to use these Force-Sensitive Resistors, so I used that as a way to control brightness.

The white LED moves every second to bring in a new color – much like time was counting down until the new year.

On the lowest brightness, this was more than bright enough to wear the entire night. The battery had plenty of capacity to run this for several hours. The highest brightness was blinding on the walk home, but lit up the sidewalk / distracted traffic.

The source code for the hat can be found here on GitHub.

Cubieboard2, A20 Guide - Sun August 11, 2013

Arch Linux ARM on the Cubieboard 2 A20

I received my Cubieboard2 (A20) last week and finally had time this weekend to get it up and running. Since I ran into a few different issues, I decided to make this into a useful post in case anyone else can benefit from it. At the end, I’ve linked to other useful guides I found.

Before I get started, let me just mention that IO Technologies, LLC did a surprisingly fast shipping job. I ordered it on Monday and it was delivered on Wednesday via USPS. Shipping coast to coast in that time is impressive. (No, I don’t get kickbacks from this. I’m just rarely impressed by companies other than newegg)

What you’ll need to follow this guide:

- Cubieboard 2, A20. The A10 uses a different kernel, sun4i, I believe.
- Another linux machine (the ability to use fdisk along with installed support for vfat and ext4)
- microSD card

microSD Card Partition and Formatting

There are a couple ways to setup the SD card. Since I plan on moving the root partition to an external SATA drive, I went separated the boot and root partitions on the SD card. Here’s how I set that up.

You’ll need to run these commands as root.

Determine what the SD card device is:

fdisk -l

For this example, we’ll call it “/dev/sdb”

Use fdisk on the SD card’s device:

fdisk /dev/sdb

Inside of fdisk, there are a few commands, type m and hit enter to see the extensive list. We’re going to create two partitions, one of 20MB, and the second (root) partition will use the rest of the space.

First we’ll print the current partition table. (For the moment, ignore the fact that this is setup how we want it)

Command (m for help): p

Disk /dev/sdb: 8082 MB, 8082423808 bytes
249 heads, 62 sectors/track, 1022 cylinders, total 15785984 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x03ca731a

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048       43007       20480   83  Linux
/dev/sdb2           43008    15785983     7871488   83  Linux

I started by deleting the existing partitions.

Command (m for help): d 
Partition number (1-4): 1

Command (m for help): d 
Selected partition 2

Print the table, as proof there’s nothing left:

Command (m for help): p

Disk /dev/sdb: 8082 MB, 8082423808 bytes
249 heads, 62 sectors/track, 1022 cylinders, total 15785984 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x03ca731a

   Device Boot      Start         End      Blocks   Id  System

Now that we have a clean slate, create the first (boot) partition. If you wanted a single partition on the SD card, you would simply press enter when it prompts for “Last sector”, instead of +20M.

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-15785983, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-15785983, default 15785983): +20M

Command (m for help): p

Disk /dev/sdb: 8082 MB, 8082423808 bytes
249 heads, 62 sectors/track, 1022 cylinders, total 15785984 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x03ca731a

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048       43007       20480   83  Linux

Follow the same process and create the second partition. This time fdisk asks us for the starting sector. The default is fine.

Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): p
Partition number (1-4, default 2): 
Using default value 2
First sector (43008-15785983, default 43008): 
Using default value 43008
Last sector, +sectors or +size{K,M,G} (43008-15785983, default 15785983): 
Using default value 15785983

Command (m for help): p

Disk /dev/sdb: 8082 MB, 8082423808 bytes
249 heads, 62 sectors/track, 1022 cylinders, total 15785984 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x03ca731a

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048       43007       20480   83  Linux
/dev/sdb2           43008    15785983     7871488   83  Linux

The partition table looks correct. Use w to write the partition to the device.

Command (m for help): w

Next, we’ll use the mkfs linux commands to format our new partitions. U-Boot reads from a vfat partition (by default), but I want the root to reside on ext4.

mkfs.vfat /dev/sdb1

mkfs.ext4 /dev/sdb2

Now our SD card is ready to use. It has partitions setup properly and they’re formatted correctly.

Copy files to the SD card

I used both the installation guides from because the steps were slightly different and I needed information from both to understand what I was doing. Cubieboard A10 Cubieboard2 A20

Here we create directories used for mounting the SD card partitions and another to extract the arch linux file system. You may omit the latter here, if you find you can write the bootloader AFTER extracting the filesystem – but I didn’t see that working properly in my brief tests.

mkdir -p mnt/boot
mkdir -p mnt/arch
mkdir source

Mount partitions

mount /dev/sdb1 mnt/boot
mount /dev/sdb2 mnt/arch

First download and extract the root filesystem to the ‘source’ folder we created. Again, I had issues writing the bootloader AFTER extracting, so I took precautions to make sure it worked properly. This is why we have the awkward step of extracting this archive just to get at the files in /boot.

tar xvzf ArchLinuxARM-sun7i-latest.tar.gz -C source

Write the bootloader to the SD card.

dd if=source/boot/sunxi-spl.bin of=/dev/sdb bs=1024 seek=8
dd if=source/boot/u-boot.bin of=/dev/sdb bs=1024 seek=32

Now we’ll extract the archive again, this time to the root partition.

tar xvzf ArchLinuxARM-sun7i-latest.tar.gz -C tmp/arch

According to the manpage, The sync command is used to “force completion of pending disk writes (flush cache)”.

Create a “boot” folder in the boot partition. This is where we’ll place files U-Boot will look for.

mkdir mnt/boot/boot

Next, we copy the script.bin, uEnv.txt, and uImage over to the boot partition.

cp mnt/arch/boot/script.bin mnt/boot/boot/script.bin
cp mnt/arch/boot/uImage mnt/boot/boot/uImage
cp mnt/arch/boot/uEnv.txt mnt/boot/boot/uEnv.txt

I had copied a few lines from another blog post, describing what uEnv.txt was meant to look like. The stock uEnv.txt only had the machid.

My uEnv.txt now looked like this:

boot_mmc=fatload mmc 0 0x43000000 ${fexfile}; fatload mmc 0 0x48000000
${kernel}; printenv; bootm 0x48000000
extraargs=rootwait disp.screen0_output_type=3

The printenv command was mentioned on forums as a way to extract more info on boot (viewable from serial).

The disp.screen0_output_mode is prefixed with EDID to tell the kernel to use the EDID from the monitor if it can, otherwise, fallback to 1280x1024 at 60Hz. disp.screen0_output_type=3 means use HDMI.

At this point, I had unmounted the SD card and put it in the Cubieboard, but it would not boot – not even to the stock NAND Android. I remembered seeing in some forum posts that there’s a serial interface you can attach to for troubleshooting boot issues.

I hooked up my FTDI USB Serial with some jumper cables I had been using for XBee testing. Details on how to hook this up can be found at this link: Cubieboard TTL Serial. NOTE: Be sure to leave VCC disconnected, as it may fry the Cubieboard otherwise.

My variation looked like this:

Next, I wrote a little python script to read and dump the serial port.

import serial

if __name__ == "__main__":
	SERIAL_PORT = "/dev/tty.usbserial-A100RYUU"
	BAUDRATE = 115200
	port = serial.Serial(port=SERIAL_PORT, baudrate=BAUDRATE, timeout=1.0)

	print( "opening serial port %s, listening at %i" % (SERIAL_PORT, BAUDRATE) )

	lineno = 0
	while True:
		line = port.readline().rstrip("\n")
		if line:
			print("%03i: %s" % (lineno, line))
			lineno += 1

This allowed me to examine the kernel output messages and find these useful lines:

655: [    0.000000] Kernel command line: console=ttyS0,115200 root=/dev/mmcblk0p1 rw rootwait loglevel=8 panic=10 rootwait disp.screen0_output_type=3

1144: [    5.250426] VFS: Mounted root (vfat filesystem) on device 179:1.
1145: [    5.261568] devtmpfs: error mounting -2
1146: [    5.265767] Freeing init memory: 188K
1148: [    5.277228] Kernel panic - not syncing: No init found.  Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.

First of all, the kernel command line is picking up the options I specified in “extraargs” in uEnv.txt, this is good.

However, “VFS: Mounted root (vfat filesystem)”, tells me it loaded the wrong root file system. Our root filesystem is ext4, not vfat.

Thirdly, Kernel panic is why we’re not booting. But wait – why couldn’t it find init? Ah yes, because the root filesystem is incorrect. So it tried to load init from the first (boot) partition, which only contains three files.

uEnv.txt tweaks

Now that we have more information, we can tweak uEnv.txt to instruct the kernel to mount the root filesystem from the second partition on the SD card. (Eventually, we could point this to an SSD on the SATA port).

For completeness, here’s the uEnv.txt that actually works:

boot_mmc=fatload mmc 0 0x43000000 ${fexfile}; fatload mmc 0 0x48000000
${kernel}; bootm 0x48000000
extraargs=rootwait disp.screen0_output_type=3 root=/dev/mmcblk0p2

Arch Linux should now boot on the Cubieboard2. I’m off to toy around with the dual core A20!


Rasterizer and Ray Tracer source released! - Mon August 05, 2013

I managed to take some time to package my rasterizer and ray tracer source code from one of my earlier posts (wow it’s been over a year). It’s posted on my github page. Funny enough, I packaged it while watching one of John Carmack’s talks from Quakecon 2013 (I absolutely must go next year). I aptly named the project, “photon”, which generically describes my adventures with computer graphics. So far, the package contains a rasterizer and a ray tracer. You’ll need CMake to build everything (projects and dependencies).

My current project is almost finished (more on this when it is ‘complete’). I ordered a cubieboard today - so maybe I’ll throw together a post when I receive it. I think it will work better for one of my hardware projects that I’m currently using my RaspberryPi with.

Scarce - Sun June 30, 2013

It’s been a while since my last post. I could cite excuses but I would rather focus on current projects and positive directions for the future.

The Ouya launched this past week. I’m excited about where games are headed because of it. There are rumors that Google is working on their own Android console and if I had to guess - Apple is working on their own as well. The war for the living room is long from over.

In my previous post I had been prototyping a new graphics rendering system. I’m happy to report positive results thus far after having integrated it into my latest code base, gemini.

I’m currently working on a shooter with an experimental theme. I have partially ported the code base to Android. It runs, but is missing audio at the moment. Once the game is complete, I’ll get back to the porting to release it on Android.

This year's posts