Cross-Lib and games that use it (e.g., Cross Chase, Cross Shoot, Cross Bomber, Cross Snake, Cross Horde)
by Fabrizio Caruso (firstname.lastname@example.org)
The universal retro-hardware abstraction layer: Use the very same code for about 200 vintage computers, consoles, calculators and other devices.
Read the Disclaimer.
The logo was designed by Hamlet.
Cross-Lib is a retro-hardware abstraction layer for coding "universal" games with the very same code for hundreds of mostly 8-bit systems (consoles, computers, scientific calculators, hand-held consoles, arcade boards, hacked toy computers, etc.).
Cross-Lib is a WORA (Write Once Run Anywhere) framework for vintage systems, i.e., you code a game once in an abstract hardware-agnostic way and Cross-Lib produces the very same game for about 200 vintage systems.
A DETAILED ARTICLE ABOUT CROSS-LIB
Here you find an article (first appeared in the French magazine "Programmez! Hors série #6") that describes Cross-Lib in details (currently only in French but there will be an English and Italian version in future).
These games are the proof of the flexibility of Cross-Lib.
Play the games online:
- Cross Verbix is a word game that looks like Tetrix with letters.
- Cross Horde is a zombie shooter with several different enemies, levels, power-ups and special items to pick.
- Cross Snake is my personal re-interpretation of Nibbler (arcade game) to which I have added more game elements. It has 50 secrets and several items to discover.
- Cross Bomber is a mini-game and clone of Air Attack (aka Blitz).
- Cross Shoot is a shooter somehow similar to Robotron. It has many items and secrets to discover.
- Cross Chase is somehow similar to Gnome Robots. The main difference is that it is a real-time game and that it has several items and power-ups to pick.
CURRENTLY SUPPORTED SYSTEMS AND ARCHITECTURES
Cross-Lib can be used to build games for about 200 different vintage systems (computers, consoles, hand-helds, arcade boards, scientific pocket calculators, etc.). A partial list of the supported systems with their status is in:
The most significant supported vintage CPU architectures are:
- COSMAC RCA 1802
- Intel 8080
- MOS 6502
- Motorola 6803
- Motorola 6809
- TMS 9900
- Zilog 80
Cross-Lib has also some experimental support for vintage 16-bit and 32-bit systems and for the native PC console.
For a more complete list of architectures you can look at:
Cross-Lib provides a full tool-chain to build universal vintage 8-bit games.
- a library with hardware-agnostic APIs for game development;
- scripts that convert automatically compiler-agnostic graphics assets to target-specific graphics assets formats;
- makefiles that handle the build process;
- the "user-friendly" script
xlto manage game projects (see the subsequent sections below).
The build process
When a game is built for a specific target, the Cross-Lib tool-chain will automatically:
- if needed, convert the abstract graphics assets in graphics assets for the given target on the fly;
- compile the game code (and the target-specific game assets) by using the appropriate compiler;
- if needed, whenever possible, create a disk/cassette/cartridge image.
In most cases the user will just have to
- code in C a game that uses Cross-Lib APIs;
- draw the graphics assets;
- run the
xlscript to create, build and test the game.
xl script will trigger the full build process which will produce the target specific version of the project
or massively build the same project for several targets (or even build several projects for one or more targets).
For example for the build of a project for the sole GameBoy target we may repressent
the interractions of various Cross-Lib components with this diagram:
Code written in C with Cross-Lib can be compiled by several different cross-compilers and natively on the PC.
The tool-chain currently supports:
For more details on the supported compilers we refer to:
Cross-Lib is meant to be used under a POSIX environment (Windows+Cygwin, Linux, etc.).
In order to be able to build the games and tests on all
default targets you need:
python(2.x or 3.x)
ncurses(necessary only for native builds)
- cross-compilers (necessary to build for vintage targets)
javaonly to build disk images for the Apple//e and Apple][ targets
For the compilers to work, you may need to add the location of their binaries to the
$PATH environment variable and to add the execution rights to those binaries.
If the compiler's binary cannot be found, you may have to set their paths in:
For more details on the prerequisites we refer to:
INSTALLATION OF THE TOOL-CHAIN
The tool-chain Cross-Lib can be installed on different POSIX-compliant enviroments. It has been tested on:
- Windows (7, 10) +
- Linux Ubuntu 18.04 under the Windows Subsystem
- Linux (KUbuntu 18.04, Lubuntu 21.10)
- FreeBSD 13.0
Cross-Lib itself does not require any installation. It is just a source library and scripts that is ready to use as is, by just downloading or cloning the content of this repository. For example you can do it by:
git clone https://github.com/Fabrizio-Caruso/CROSS-LIB.git
In order to use Cross-Lib you will need to install the prerequisites described in the previous section. The way these prerequisites are installed vary depending on the environment.
Under Windows + Cygwin
For Windows + Cygwin the tested and verified installation procedure uses:
Cygwinsetup to install
CC65is installed under Windows by just downloading and decompressing its snapshot (https://sourceforge.net/projects/cc65/).
Z88DKis installed under Windows by downloading and decompressing its latest nightly build (http://nightly.z88dk.org/).
ACKare installed from sources. Look at the installation procedure under Linux for the details.
LCC1802is installed under Windows by simply decompressing its released binary version (https://github.com/bill2009/lcc1802/releases).
For Linux (native or under thw Windows Subsystem), the tested and verified procedure both standard repositories and installation from sources.
A detailed procedure for recent Ubuntu distributions is described here:
HOW TO START
Inside the project main directory, you find the
src and the
srccontains the source code and all other files that are necessary to build the games and tests
buildis supposed to be empty at first and it is the target directory for the build process.
First of all you need to be in the
src you can use the
xl script (or the
make command) to do different operations on projects.
For a description of the
xl script and its parameters, take a look at the next sections.
xl is found inside the
src directory and it is meant to be used from
Make sure that it has execution rights (
chmod +x ./xl) and, for your convenience, that the current directory
. is included in
Its name stands obviously for
Cross-Lib as it can execute most of the operations people may want to do with Cross-Lib.
It can be used to create, build, delete and perform other operations on all Cross-Lib projects (tests, built-in games and custom games).
xl is used as follows:
xl <command> <[optional] parameters>
You can display its instructions and some examples by using:
xl help <[optional] command>
where commands are
The following sections will show how to use this script in the my common use-cases.
We recommend to use
xl build to build projects. Alternatively you can use
xl build (recommended)
I recommend that you use
xl build [game_or_test_name] [optional system_name] [optional number of threads]
A convenient shortcut is using just
xl as follows:
xl [project_name] [optional system_name] [optional number of threads]
[optional system_name] parameter is the name of the target. If no target is specified then the native target (the host terminal) is implied.
[optional number of threads] is used to specify the number of threads to use for multiple targets that can be built in parallel.
xl build snake-> It builds Cross Snake for the native console by using
xl build bomber atari-> It builds Cross Bomber for the Atari 8-bit target (by using the appropriate cross-compiler, i.e., CC65)
xl build snake vic20-> It builds Cross Snake for the Commodore Vic 20.
xl build games msx-> It builds all game projects for the MSX target (by using the appropriate cross-compiler, i.e., the ones in Z88DK).
xl build bomber cc65_targets-> It builds Cross Bomber for all targets that use CC65.
xl build tests c64-> It builds all tests for the Commodore 64 target
Remark: All binaries will be in the
build directory (same depth level as
make (NOT recommended)
Using a standard
make command is possible but you will get fewer options.
For game projects you can use:
make [system_name] -f ./games/[game_name]/Makefile.[game_name]
For test projects you can use:
make [system_name] -f ./tests/[test_name]/Makefile.[test_name]
For more details and examples on build instructions for both
xl build and
make we refer to:
CREATING A NEW GAME PROJECT
In order to create a new game project we can use the
xl create scripts that will create the necessary initial source code files, graphic assets and Makefile inside a folder in the
The script is used as follows:
xl create [game project name] [initial code type]
[initial code type] can be
helloworldor empty for initial code that only displays 'hello world'
gamefor an initial code for a standard game with a main loop and a level loop
apisfor an initial code that uses most APIs.
xl create foo-> It creates a new game project
foowith a trivial code that initializes sound, input and graphics and just displays
hello worldon the screen.
xl create bar game-> It creates a new game project
barwith code that initializes sound, input and graphics and contains the main loops that may be used in a standard game.
xl create foobar apis-> It creates a new game project
foobarwith code that initializes sound, input and graphics and contains code that shows how to use most APIs.
RESETTING A PROJECT BUILD
In order to remove generated graphics assets of a specific project and other temporary files that are produced during a build, you can use
Use this command if you want to regenerate the graphics assets of a specific project.
xl reset [project name]
Project-specific graphics assets and temporary files including project-specific ones are removed. Built binaries are preserved.
xl reset foo-> It deletes generated graphics assets and temporary files for
CLEANING TEMPORARY FILES AND BINARIES
If you want to remove built binaries and temporary files that are produced during a build you can use 'xl clean'.
xl clean [optional project name]
If you provide a project name, then also project-specific temporary files are removed including generated project-specific graphics assets.
xl clean-> It deletes all built binaries and some generic temporary files (not the once inside project directories).
xl clean foo-> It deletes the same files as
xl cleanand also deletes temporary files found inside the
You can list all current game and test projects with
which searches both
games folders for projects (both built-in and user-defined) and produces a list with all of them.
Non-built-in game projects can be deleted trhough the
xl delete script in a very simple way:
xl delete [game project name]
xl delete foo -> It removes the
foo source code, assets and Makefile files
Thanks to Cross-Lib APIs, the game code can be hardware-agnostic. Using only Cross-Lib APIs is not enough, though, as Cross-Lib covers targets that have different screen size, screen shape and targets that lack some hardware features such as graphics, colors, sounds.
ANSI C (A sub-set of)
The code has to be compiled by several different compilers that do not necessarily support the latest version of the C standard. Therefore it should be written in a sub-set of ANSI C89 that is common among all supported compilers.
This sub-set can be described as (mostly) ANSI C89 without:
structcopies, assignments, parameters (use pointers to
- dynamically allocated memory (
Moreover for performance reasons it is better to avoid recursion (as this has an extreme high cost on MOS 6502 targets).
Some C99 features are available:
//comments are allowed.
stdint.his not available but
uint16_tare (with no need for extra include directive).
Using Cross-Lib APIs is not enough as the screen size and shape may be different.
Cross-Lib exposes a constant
XSize for the width of the screen and a constant
YSize for the height of the screen.
Both these macros are measured in terms of numbers of tiles (see next section).
The game code should rely on fractions of
XSize and of
YSize and never use hard-coded sizes or use conditional directives to cover all sizes.
By doing so, upon compilation, the game will auto-adapt to the target's screen size.
Graphics in Cross-Lib is tile-based as this is the only possible graphics that can be supported by all targets. For targets with graphics, the shapes of tiles are only defined at compilation time and cannot be re-defined. So, for targets with graphics, smoothly moving sprites can only be implemented as software sprites through pre-shifted tiles.
Most targets with graphics have 8x8 pixel tiles but some other targets with graphics have different shapes. So do not implement logic that only assumes 8x8 pixel tiles (e.g. when implementing software sprites with pre-shifted tiles). If you want to support targets with no graphics (i.e., tiles are just mapped to ASCII characters), you either avoid code that depends on tile shapes or if you, you have to implement an alternative version for non-graphics targets.
For example for the game Cross Snake you can see how it is rendered on the MSX 1 (graphics, sounds, colors) and on the Game Boy (graphics, sounds but no colors):
For more snapshots we refer to:
Colors, Sounds and Graphics
Some targets have no colors or no color on text, or no sounds, or no graphics. So do not write any logic that relies only on the presence of colors/sounds/graphics; or if you do, use conditional directives to implement an alternative logic for targets with no colors/sounds/graphics.
Learn from the built-in games and tests
Cross-Lib comes with games and tests whose code can be used to learn how to code universal games.
The code of the games is in:
The code of the examples is in:
Cross-Lib provides several APIs that allow to code games in a hardware-agnostic way for all supported targets. The currently available APIs are described at
LOADING THE GAMES
In order to run the game you will have to follow a different procedure depending on whether you want to load it into an emulated system or a real system.
Loading the game into an emulated vintage system
In most cases loading an executable into an emulator is straightforward. For a detailed guide on how to load the game on several emulated systems for which the procedure is not obvious, we refer to:
Loading the game into a real vintage system
This depends on the systems and the format used to store the game. For some hints on this take a look at:
The main future goals are
- improving the exposed APIs
- supporting more cross-compilers, native compilers, systems and sub-targets
- adding more features to Cross-Lib (e.g., more redefinable tiles, more sound effects, etc.)
- coding more universal games and demos
Cross-Lib would not exist without the cross-compilers and the support of their developers and the support of some people who have helped me handle the input/output of some targets.
A partial list of the people who have helped in found in: https://github.com/Fabrizio-Caruso/CROSS-LIB/blob/master/docs/CREDITS.txt
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for non-commercial applications, subject to the following restrictions:
The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
This notice may not be removed or altered from any source distribution.