Category Archives: Software

Minus Infection

I took a programming languages class in college, which used Scheme to demonstrate concepts like lexers, parsers, etc. The final project was to write our own interpreted object-oriented language. I enjoyed the class but never quite got the hang of Scheme. So when the time came to write the language, I did the minimum possible in Scheme, and implemented the rest as a standard library add-on to my own language.

Cutting things to the bare minimum resulted in a language with only seven constructs, and the only arithmetic operation was subtraction. Addition would thus be implemented as minus (a, minus(0, b)). IF statements were simply WHILE loops that ran zero or one times. And so on.

Sadly, I don’t have the source code any more. But I do have the README file.

Minus Infection
A Programming Language by
Greg Kennedy

I. Introduction
What is Minus Infection? MI is a programming language which aims to be Turing complete and support object-oriented programming with as few primitives as possible. It is written in Scheme. Functionality is provided by external Library files, which define many of the functions you would otherwise miss from your favorite language.
Because of this, the actual implementation of MI is rather simple, but powerful enough that you can use the built-in functions to build vastly more complicated ones.

But why? Scheme is a fine language. It is really quite powerful. But I just can’t get the hang of all those parentheses and cars and cdrs. So I thought I’d minimize the work I had to do in Scheme, and instead move that work into MI. It’s also sort of an experiment for me to discover just how little is really needed to make a usable language.

II. How do I use it?
MI source files are simply text files – create them in Notepad or vi or whatever.
Your source file is the main routine of your program.

III. What are the primitives?
MI recognizes as “true” any expression which evaluates to less than 0, and “false” as any expression which evaluates to “equal to or greater than 0” (i.e. “not false).

The only variable type MI understands is integer arrays. You can create single variables in your source and omit the subscript when later referencing them – the parser will simply fill in the missing subscript with a [0].

See section 4 for methods for dealing with strings. Internally they are represented (like in C) as an array of integers representing character codes.

Arrays maintain their own sizes and will warn of an out-of-bounds access. For strings, no special termination character is needed.

These primitives are built-in to MI:
MINUS (X, Y) – perform the calculation X – Y and return the result.
LTZ (X) – returns -1 if X is less than 0, 0 otherwise.
WHILE (COND, BLOCK) – continually executes BLOCK as long as COND is true.
SET (X, EXP) – sets X to the evaluated result of expression EXP.
DEFINE (NAME, PLIST, BLOCK) – sets
INT (NAME, SIZE) – declares an array named NAME of length SIZE
DOT (NAME, MEMBER) – OO operator: call member function or access member variable
PRINT (x) – Prints X to the screen. X is a string.

IV. What is in the libraries?
You’ve no doubt noticed that the language seems a little sparse. That’s because all the real functionality comes from the libraries.
To load a library, simply place this command in your source file:
LIB “FILENAME” – when parsing, this line causes the execution of FILENAME.

The standard library is called default.lib. It provides the following functions:
< (X, Y), > (X, Y), = (X, Y),
<= (X,Y), >= (X, Y) – Conditionals returning true if X (op) Y.
IF (COND, BLOCK1, BLOCK2) – if COND is TRUE, executes BLOCK1; else executes BLOCK2
– (X, Y) – behaves like MINUS
+ (X, Y) – calculates X + Y, returns result
*, /, % (X,Y) – multiply, divide, modulus
NAND(X,Y), NOR(X,Y), NOT(X),
AND(X,Y), OR(X,Y), XOR(X,Y) – boolean operations.
FOR(X, COND, INC, BLOCK) – Similar to C for loops
STRCPY (X, Y) – copies string Y over string X.

V. Example code?
This program prints “Hello, World!” to the screen.

LIB "default.lib"
VAR (HWORLD, 14);
STRCPY(HWORLD,"Hello, World!");
PRINT(HWORLD);

0dbfs.pl: Bringing a Nuke to the Loudness War

Ever heard of the Loudness War? It’s the steady ramp-up in perceived volume that has plagued popular music for the past 30+ years. Producers have steadily chipped away at dynamic range in an effort to make a hotter track. Audio signal-to-noise ratio suffers. Nowadays the typical radio song has a 3-6 dB dynamic range (for comparison, CDs have a theoretical 96 dB range).

Well folks: I’m playing to WIN. Here is a compressor that scales ALL of your peaks to 100%: in other words, compression at a ratio of INFINITY : 1… or a dynamic range of 0. TAKE THAT, PRODUCERS.

Here’s an example in action, cutting from Clair de Lune. First, the original. Then, the RADIO-READY version.

Doesn’t this just sound so much more… hip / edgy / loud / etc?

Interestingly, I tried it on a selection of pop music. It makes for a great demonstration of “listener fatigue”.

0dbfs.zip – zip file containing Perl script, 1.7 kB

cfg_parse – Simple Config File Parser in C

There is no standard way in C to parse config files. Several libraries have sprung up to solve the problem, but perhaps that is overkill for what should be a simple operation.

Presenting: cfg_parse – a compile-in solution for reading key-value pairs from file(s), looking up settings, and writing a config file back to disk. I could write more about it, but the included main.c shows all the functionality.

// driver test program for cfg_parse

#include "cfg_parse.h"

#include <stdio.h>

int main(int argc, char **argv)
{
// Pointer to a cfg_struct structure
struct cfg_struct *cfg;

// Initialize config struct
cfg = cfg_init();

// Specifying some defaults
cfg_set(cfg,"KEY","VALUE");
cfg_set(cfg,"KEY_A","DEFAULT_VALUE_A");

// "Required" file
if (cfg_load(cfg,"config.ini") < 0)
{
fprintf(stderr,"Unable to load cfg.ini\n");
return -1;
}

// Several "optional" files can be added as well
//  Each subsequent call upserts values already in
//  the cfg structure.
cfg_load(cfg,"/usr/local/etc/config.ini");
cfg_load(cfg,"~/.config");

// Retrieve the value for key INFINITY, and print
printf("INFINITY = %s\n",cfg_get(cfg,"INFINITY"));

// Retrieve the value for key "KEY", and print
printf("KEY = %s\n",cfg_get(cfg,"KEY"));

// Delete the key-value pair for "DELETE_ME"
cfg_delete(cfg,"DELETE_ME");

// Dump cfg-struct to disk.
cfg_save(cfg,"config_new.ini");

// All done, clean up.
cfg_free(cfg);

return 0;
}

Download: cfg_parse.1.0.tar (version 1.0, 4kb .tar.gz)

iNES Header Fixer

Auditing ROM collections has been made much simpler over the years thanks to concerted efforts of many cartridge purchasers, dumpers, cataloguers, and coders.  Using a combination of RomCenter (or ClrMamePro) and a No-Intro .Dat file, one can quickly fix an entire collection in one go: repairing names, verifying regions, checking for problem ROMs, producing have-lists, etc etc.

NES roms throw a particular curveball because they carry a 16-byte header with a little info about the board within the cart.  Emulators need this info, but it isn’t verified by No-Intro since it’s not part of any real dump.  As a result iNES headers remain missing, incorrect, or filled with crap data.  A new repair tool is needed.

ines-fix.py is a Python script which can repair defunct iNES headers using an external cart database.  It does this by extracting the data portion from the file, calculating a crc32, looking for the crc the xml file, and then rebuilding a header based on that info.  If the old and new headers differ, the file is overwritten with a fixed version.

Be careful with this tool: it’s sort of a blunt object, and may trash your rom collection if not used carefully.  Make backups.  In particular it writes only iNES v1 headers, expecting emulators to cope with the shortcomings of this format.

Output samples:
-> No change to existing header

CRC check: 4318A2F8
Found CRC match: Barker Bill's Trick Shooting
*** Header unchanged: not writing replacement file.
----------------------------------------------------

-> Adding a battery

CRC check: 1F6EA423
Found CRC match: Baseball Simulator 1.000
*** HEADER UPDATED ***
oldHeader: 4e45531a081010000000000000000000
newHeader: 4e45531a081012000000000000000000
All done.  Wrote new file roms/Baseball Simulator 1.000 (USA).nes

-> Correcting a mapper, vertical mirroring, and removing “DiskDude!”

CRC check: 9BDE3267
Found CRC match: Adventures of Dino Riki
*** HEADER UPDATED ***
oldHeader: 4e45531a0204004469736b4475646521
newHeader: 4e45531a020431000000000000000000
All done.  Wrote new file roms/Adventures of Dino Riki (USA).nes
----------------------------------------------------

-> Standardizing on “horizontal mirroring”

CRC check: 3ECA3DDA
Found CRC match: Bases Loaded 3, Ryne Sandberg Plays
*** HEADER UPDATED ***
oldHeader: 4e45531a101041000000000000000000
newHeader: 4e45531a101040000000000000000000
All done.  Wrote new file roms/Bases Loaded 3 (USA).nes
----------------------------------------------------

-> Adding a missing header

CRC check: 50CCC8ED
Found CRC match: Battleship
*** HEADER UPDATED ***
oldHeader:
newHeader: 4e45531a020430000000000000000000
All done.  Wrote new file roms/Battleship (USA).nes
----------------------------------------------------

Here’s the script:

Continue reading

Timewave v1.2

Introduction
Timewave is a 2-d space shooter written in C++ using some of the freely available SDL libraries. It runs on Windows, Linux, and Mac OSX (10.4 or later). The object of this game is to fight through the mass of enemies in each level, defeat the level boss, and finally destroy the (well-armed) enemy space station far from Earth.

It has an interesting “twist” in which you can alter the flow of time. Build up your time meter by playing the game in fast-forward. Playing in slow motion affords you some extra maneuvering room but depletes the meter. If you achieve a high score, you can choose a color flag to represent your ship and have yourself recorded on the high score table.

This game is ‘freeware’ – you can download it and copy it around to anyone you like, you can even alter the graphics to better suit your tastes if you wish, but don’t pull my name off it and try to pass it off as your own work. You can’t get the source code though because it’s a total wreck. I may go and try cleaning it up later for a release, but until then, the binaries in the download should work just fine.

Screenshots
Last updated Aug. 7, 2007 – click for full-size

Recent Changelog

  • Reduction in resource file sizes: some items converted to 256-color, optipng and audio editing shaved further bytes.
  • Renamed hiscore.dat to config.ini, and added more options.
  • New command line options: -f (switch to Fullscreen mode), -c (Create Config: just write config.ini and exit), -w (switch to Windowed mode)
  • Added a “Change Keys” button which allows users to alter the inputs.
  • Added “Arcade Mode” switch to the config.ini file. This causes the game to simulate an arcade machine on Free Play: the title screen rotates with the high score table.
  • The arrow keys now drive the cursor on the high score color picker table.
  • Mac OSX port (PPC / Intel Universal Binary, 10.4 or greater).

Downloads
Last updated May 3, 2012