creatiVision BIOS Music Player Song format

Talk about programming CreatiVision (except games programming). Projects of homebrew hardware are also welcome.
Post Reply
User avatar
@username@
Posts: 320
Joined: Tue Oct 22, 2013 6:59 pm
Location: Scotland

creatiVision BIOS Music Player Song format

Post by @username@ » Sat Feb 12, 2022 6:24 pm

Here's a breakdown of the creatiVision Music Player Song format.

A little background

The BIOS Music Player uses the following tables to decode a song stream.

$FC79 - 8 element note duration table (BASIC Manual Page 103 for reference)
$FC80 - 42 element frequency table higher 4 bits (BASIC Manual Page 102 for reference)
$FCAA - 42 element frequency table lower 7 bits (BASIC Manual Page 102 for reference)
$FCD5 - 17 element volume decay table
$FCE6 - 17 element volume maximum table used by SONIC INVADERS

It's no surprise that BASIC uses the same tables, with a few interesting exceptions.

Song Pointers

The game ROMs have structure pointers, which are referenced at $BF00 + X

Pointer Structure

Code: Select all

WORD Songstream pointer
BYTE Songstream length
The songstream length is used to seed the Y register for indirect indexing.

The first byte of the songstream (last as Y decrements - so reading backwards!) is the note length.

Subsequent bytes are encoded as frequency table index shift left 3, plus the duration.

Air/Sea Attack Intro

Ok - here's the whole intro tune from Air/Sea Attack.

Code: Select all

77 4F 37 4B 05 BB 4F 27 83 93 9B 93 17 4F 96 AB 17 4F 0E
Reading backwards you get

Code: Select all

$0E - Note length
$4F - Frequency index 9, duration 7
$17 - Frequency index 2, duration 7
$AB - Frequency index 21, duration 3
and so on
Decoded to BASIC it would be

Code: Select all

10   SOUND 9;7,2;7,21;3
20   SOUND 18;6,9;7,2;7
30   SOUND 18;3,19;3,18;3
40   SOUND 16;3,4;7,9;7
50   SOUND 23;3,0;5,9;3
60   SOUND 6;7,9;7,14;7
When you try to play in BASIC there's an obvious timing issue. This is due to the note length.
BASIC has it preset to $12, Air/Sea attack has it set to $0E.

The problem is caused by this code, which is the same in all versions of BASIC

Code: Select all

7BF9: lda #$12
7BFB: ldy $D1
7BFD: sta $0210,y
7C00: jsr $7C14
The note length is hard coded to be $12. A quick patch would make it sound better
at least - and maybe help when composing your own tunes in a different timing.

What is BASIC Frequency 1 Rest?

In the manual, 1 and 32 are defined as rests. This is not actually the case for frequency code 1 - in the player it has a special meaning!

When the player encounters a frequency code of 1 - it means take the next byte in the song stream and use it as a literal index.
This is how game ROMs access the missing upper elements in the frequency tables.

So a stream of $1F, $0B is decoded to

Code: Select all

$0B - frequency code 1, duration 3
$1F - Impossible from BASIC - used by several games
The code which kills this little trick in BASIC is

Code: Select all

7BBA: lda $CF
7BBC: and #$1F
7BBE: cmp #$01
7BC0: bne $7BC4
7BC2: lda #$00
7BC4: sta $D0
Any attempt to use frequency duration 1 is returned to 0.

By making a couple of patches to BASIC, you can use it to compose your next in game masterpiece in an emulator!

File offsets for patching are (same for all BASIC8xx.BIN)

$2BC3 - Change 0 to 1 - thus putting back the literal byte command
$2BFA - Change note length

Cheers!
User avatar
Scouter3d
Posts: 646
Joined: Mon Jun 28, 2010 7:02 am
Location: Wien
Contact:

Re: creatiVision BIOS Music Player Song format

Post by Scouter3d » Sat Feb 12, 2022 6:56 pm

Amazing as always!
Cheers, TOM:0)
Post Reply