Skip to content

A tiny SFX (~300 bytes) engine for the Amstrad CPC

Notifications You must be signed in to change notification settings

davemoore22/cpcsfx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CPCSFX

This is a tiny (currently under ~300 bytes) (non-firmware) SFX engine for the Amstrad CPC that I code to use in my game Reginald and the She Vampires (https://typhonsoft.itch.io/reginald). Current version is 0.1, released 18th December 2025. Code is released under the GPL2.

Its not a replacement for Arkos Tracker support or anything like that. Its just an example of how to prod the PSG chip directly in Z80 machine code. I'm sure there's plenty of enhancements to be made, and there's probably bugs in it. I used ChatGPT to generate the data values for the notes, but I built the code up through ridiculous amounts of trial and error from first principles (I knew some Z80 but not how to produce sound) of producing a single tone using Z80 as there's not really anywhere on the internet that describes how to prod the CPC soundchip from the ground up. Everywhere uses Firmware or some sort of prebuilt engine.

You shouldn't really use this unless you have to, and the sounds aren't much cop, but they are indeed vaguely recogisable SFX!

Where possible you should use the lovely Arkos Tracker at https://www.julien-nevo.com/arkostracker/ and the CPCTeleraNext engine at https://github.com/Arnaud6128/cpctelera/commits/SDCC_4.5.0_next/ if you can instead.

I've included some sample sfx and a CPCTelera project binding the necessary routines to use them. Load and run the DSK, and press Keys A to H to hear them (the border of the screen will change colour when playing a sfx).

  • A - footstep
  • B - get an item
  • C - enemy spawn
  • D - show hint alert
  • E - open a door
  • F - use a bomb
  • G - kill a monster
  • H - shoot a bullet

Currently the Engine takes 299 bytes, and the data for the eight sample sounds is 289 bytes.

Effect format

Data for a Sound Effect is made up of a number of different notes (optionally including rest/silent notes), and these are all sequentially played after ope another on Channel A. There is an initial byte for the note count (including any rest notes), followed by the notes themselves (9 bytes each).

Note format

If you look at the data file, you'll see the Note format is:

; Note format for each note (9 bytes):
; .dw period
; .db duration
; .db volume
; .db flags (noise, envelope, vibrato)
; .db noise period
; .db envelope
; .db vibrato depth
; .db vibrato speed

Example

A simple example with one note followed by a silence (rest) note:

.globl				_sfx_footstep

_sfx_footstep:

	.db				2 ; note count (including rest notes)

	.dw 			0x0200 
	.db				4 
	.db				10 
	.db				FLAG_ENV | FLAG_NOISE
	.db				14
	.db				0x0D
	.db				0
	.db				0

	.dw				0x0000
	.db				4
	.db				0
	.db				0
	.db				0
	.db				0
	.db				0
	.db				0

To use this in CPCTelera, like I have done, make the data visible to your code:

extern const unsigned char sfx_footstep[];

And then queue it by calling one of the exposed functions:

 sfx_start((void *)sfx_footstep);

To actually play sounds though, you need to call another method, sfx_update() regularly (in the example code I do this in the main loop):

cpct_waitVSYNC();
sfx_update();

Note sfx_update() is perfectly interrupt-safe, I call it in my own custom interrupt handler in Reginald (https://typhonsoft.itch.io/reginald) once every 1/50 of a second (6 frames), that's probably the preferred way of doing things.

There is also another method exposed called sfx_stop() which stops all output immediately.

Important note about compiling

Please note this uses the new calling convention used by SDCC4.5, and thus needs the CPCTeleraNext branch developed by Arnauld to compile. Feel free to fork and improve, I am sure I have made some mistakes somewhere, and my understanding of sound/sfx concepts is not great, but there's plenty of room to add new features. Let's try and keep the player under 512 bytes if possible, and if possible, keep it to sFX only.

Ideas for future enhancements:

  • Multi-channel
  • Pitchslide

About

A tiny SFX (~300 bytes) engine for the Amstrad CPC

Resources

Stars

Watchers

Forks

Packages

No packages published