Space Invaders 1999 ZSNDWIN files

Codecs, formats, encoding/decoding of game audio, video and music
DeevDaRabbit
Posts: 6
Joined: Thu Jan 12, 2023 11:54 pm

Space Invaders 1999 ZSNDWIN files

Post by DeevDaRabbit »

I would like to know if QuickBMS has a script that can detect ZSNDWIN (.zsd) files from the 1999 Space Invaders for PC.
If not, I hope I can request for there to be a script made at some point in time, as I'm working on a remake of the game.
BloodRaynare
Posts: 367
Joined: Fri Mar 10, 2017 7:23 am

Re: Space Invaders 1999 ZSNDWIN files

Post by BloodRaynare »

ZSD (ZSND***) is a Z-Axis' audio resource format. Depending the type of it, creating a BMS script should be doable.
Anyway, send a sample file please.
DeevDaRabbit
Posts: 6
Joined: Thu Jan 12, 2023 11:54 pm

Re: Space Invaders 1999 ZSNDWIN files

Post by DeevDaRabbit »

BloodRaynare wrote:ZSD (ZSND***) is a Z-Axis' audio resource format. Depending the type of it, creating a BMS script should be doable.
Anyway, send a sample file please.
https://drive.google.com/file/d/1YJq-dy ... share_link
Here.
BloodRaynare
Posts: 367
Joined: Fri Mar 10, 2017 7:23 am

Re: Space Invaders 1999 ZSNDWIN files

Post by BloodRaynare »

Here's a BMS script to extract the raw PCM audio inside the ZSD file to WAV

Code: Select all

IDString "ZSND"
getDstring PLATFORM 4
get ZSD_SZ long
get HEADER_SZ long

## Set the variable for the resulting WAV files
math CODEC_ID = 1
math CHAN = 1
math WAVEFORMATEX_SZ = 16
math BITS = 16

## Populate the entry offsets and their number of entries for each of them

for i = 0 < 7
	get ENTRY_NUM long
	get ENTRY_OFF long
	
	putarray 0 i ENTRY_NUM
	putarray 1 i ENTRY_OFF
next i


## Obtain the audio frequency info

getarray ENTRY_NUM  0 1
getarray ENTRY_OFF  1 1
getarray TMP        1 2

xmath ENTRY_SZ "(TMP - ENTRY_OFF) / ENTRY_NUM"
xmath PAD "ENTRY_SZ - 8"

goto ENTRY_OFF

for i = 0 < ENTRY_NUM
	get NUM short
	get UNK short
	get FREQ long
	getDstring ZERO PAD
	
	putarray 2 NUM FREQ
next i

## Obtain the offset and the size of the audio data

getarray ENTRY_NUM  0 2
getarray ENTRY_OFF  1 2
getarray TMP        1 3

goto ENTRY_OFF

for i = 0 < ENTRY_NUM
	get OFFSET long
	get SIZE long
	
	putarray 3 i OFFSET
	putarray 4 i SIZE
next i

## Add the RIFF header to the audio data then extract it to WAV
getarray ENTRY_NUM  0 2

for i = 0 < ENTRY_NUM
	getarray FREQ     2 i
	getarray OFFSET   3 i
	getarray SIZE     4 i
	log MEMORY_FILE 0 0
	log MEMORY_FILE OFFSET SIZE
	callfunction WAVHeader 1
	get WAV_SZ asize MEMORY_FILE3
	string NAME p "%04d.wav" i
	log NAME 0 WAV_SZ MEMORY_FILE3
next i

startfunction WAVHeader
	log MEMORY_FILE2 0 0
	log MEMORY_FILE3 0 0

	append
	
	putDstring "WAVEfmt " 8 MEMORY_FILE2
	put WAVEFORMATEX_SZ long MEMORY_FILE2
	put CODEC_ID short MEMORY_FILE2
	put CHAN short MEMORY_FILE2
	put FREQ long MEMORY_FILE2
	xmath BYTE_RATE "(FREQ * CHAN * BITS) / 8"
	put BYTE_RATE long MEMORY_FILE2
	xmath BLOCK_ALIGN "BITS / 8"
	put BLOCK_ALIGN short MEMORY_FILE2
	put BITS short MEMORY_FILE2
	putDstring "data" 4 MEMORY_FILE2
	put SIZE long MEMORY_FILE2
	log MEMORY_FILE2 0 SIZE MEMORY_FILE
	
	get TMP_SZ asize MEMORY_FILE2
	
	putDstring "RIFF" 4 MEMORY_FILE3
	put TMP_SZ long MEMORY_FILE3
	log MEMORY_FILE3 0 TMP_SZ MEMORY_FILE2
	
	append
endfunction
̶N̶o̶t̶e̶:̶ ̶M̶i̶g̶h̶t̶ ̶f̶a̶i̶l̶ ̶w̶i̶t̶h̶ ̶s̶o̶m̶e̶ ̶f̶i̶l̶e̶s̶,̶ ̶s̶p̶e̶c̶i̶f̶i̶c̶a̶l̶l̶y̶ ̶t̶h̶e̶ ̶o̶n̶e̶ ̶w̶h̶e̶r̶e̶ ̶t̶h̶e̶ ̶n̶u̶m̶b̶e̶r̶ ̶o̶f̶ ̶e̶n̶t̶r̶i̶e̶s̶ ̶d̶o̶e̶s̶n̶'̶t̶ ̶m̶a̶t̶c̶h̶ ̶b̶e̶t̶w̶e̶e̶n̶ ̶t̶h̶e̶ ̶s̶a̶m̶p̶l̶e̶ ̶r̶a̶t̶e̶ ̶a̶n̶d̶ ̶o̶f̶f̶s̶e̶t̶/̶s̶i̶z̶e̶ ̶i̶n̶f̶o̶ ̶(̶I̶ ̶h̶a̶v̶e̶ ̶f̶e̶w̶ ̶o̶f̶ ̶t̶h̶o̶s̶e̶ ̶f̶i̶l̶e̶s̶ ̶f̶r̶o̶m̶ ̶P̶C̶ ̶p̶o̶r̶t̶ ̶o̶f̶ ̶D̶a̶v̶e̶ ̶M̶i̶r̶r̶a̶ ̶F̶r̶e̶e̶s̶t̶y̶l̶e̶ ̶B̶M̶X̶,̶ ̶w̶h̶i̶c̶h̶ ̶a̶l̶s̶o̶ ̶d̶e̶v̶e̶l̶o̶p̶e̶d̶ ̶b̶y̶ ̶Z̶-̶A̶x̶i̶s̶)̶.̶ ̶

EDIT: I've updated the script. Shouldn't fail with the ZSD files that has the number of entries mismatch between the sample rate and offset/size info.

EDIT2: Updated the scripts again, to clean the WAV parsing a little bit.

Streamed audios (usually named Music.zsd or something similar) will require a separate script, since the audio codec and how the header are constructed were different.
Last edited by BloodRaynare on Sun Jan 15, 2023 2:43 am, edited 3 times in total.
DeevDaRabbit
Posts: 6
Joined: Thu Jan 12, 2023 11:54 pm

Re: Space Invaders 1999 ZSNDWIN files

Post by DeevDaRabbit »

Thank you for your help.

Though I assume that you don't have the knowledge on how to extract the music data?
No worries if not. I can just remake the soundtrack from scratch as I'm doing currently.
BloodRaynare
Posts: 367
Joined: Fri Mar 10, 2017 7:23 am

Re: Space Invaders 1999 ZSNDWIN files

Post by BloodRaynare »

DeevDaRabbit wrote:Thank you for your help.

Though I assume that you don't have the knowledge on how to extract the music data?
No worries if not. I can just remake the soundtrack from scratch as I'm doing currently.
That would be doable too, it's just the differences is the header is much simpler and the codec data is different (Mono IMA ADPCM, at least with Freestyle BMX). Just send the file here.
DeevDaRabbit
Posts: 6
Joined: Thu Jan 12, 2023 11:54 pm

Re: Space Invaders 1999 ZSNDWIN files

Post by DeevDaRabbit »

I'll just send you them all, that should be easier.
https://drive.google.com/file/d/1RLjUSU ... sp=sharing
DeevDaRabbit
Posts: 6
Joined: Thu Jan 12, 2023 11:54 pm

Re: Space Invaders 1999 ZSNDWIN files

Post by DeevDaRabbit »

By the way, I thought I'd mention I found some interesting sound effects I don't think are used in the game that also aren't present in the N64 version's files.
Another discovery, though a disappointing one, is that all the sounds were resampled to 22kHz... Even the ones that were higher than that, making the music sound worse than it did on consoles.
BloodRaynare
Posts: 367
Joined: Fri Mar 10, 2017 7:23 am

Re: Space Invaders 1999 ZSNDWIN files

Post by BloodRaynare »

Unfortunately, I couldn't make the bms script for the streamed files, specifically I can't extract it to the WAV files due to differences in the codec data. But at least, you can use this TXTH script and play it with vgmstream (with the test.exe or the foobar2000/winamp plugins).

Code: Select all

subsong_count = @0x20
base_offset = @0x24
subsong_spacing = 8

start_offset = @0x00
data_size = @0x04

codec = DVI_IMA
channels = 1
sample_rate = 44100
num_samples = data_size
Save the text above as "sndmus.zsd.txth" and put it on the same directory as the sndmus.zsd file. Then, just drag the ZSD file (not the TXTH file!) on foobar/winamp playlist or drop the files to test.exe.
If foobar/winamp shows no duration/question mark, make sure "Enable unknown exts" are checked in the preferences.

But, if you still want to use this script anyway...

Code: Select all

IDString "ZSND"
getDstring PLATFORM 4
get ZSD_SZ long
get HEADER_SZ long

## Set the variable for the resulting WAV files
math CODEC_ID = 17
math CHAN = 1
math FREQ = 44100
math WAVEFORMATEX_SZ = 20
math BITS = 4

## Populate the entry offsets and their number of entries for each of them

for i = 0 < 7
	get ENTRY_NUM long
	get ENTRY_OFF long
	
	putarray 0 i ENTRY_NUM
	putarray 1 i ENTRY_OFF
next i

## Obtain the offset and the size of the audio data

getarray ENTRY_NUM  0 2
getarray ENTRY_OFF  1 2
getarray TMP        1 3

goto ENTRY_OFF

for i = 0 < ENTRY_NUM
	get OFFSET long
	get SIZE long
	
	putarray 2 i OFFSET
	putarray 3 i SIZE
next i

## Add the RIFF header to the audio data then extract it to WAV
getarray ENTRY_NUM  0 2

for i = 0 < ENTRY_NUM
	getarray OFFSET   2 i
	getarray SIZE     3 i
	log MEMORY_FILE 0 0
	log MEMORY_FILE OFFSET SIZE
	callfunction WAVHeader 1
	get WAV_SZ asize MEMORY_FILE3
	string NAME p "%04d.wav" i
	log NAME 0 WAV_SZ MEMORY_FILE3
next i

startfunction WAVHeader
	log MEMORY_FILE2 0 0
	log MEMORY_FILE3 0 0

	append
	
	putDstring "WAVEfmt " 8 MEMORY_FILE2
	put WAVEFORMATEX_SZ long MEMORY_FILE2
	put CODEC_ID short MEMORY_FILE2
	put CHAN short MEMORY_FILE2
	put FREQ long MEMORY_FILE2
	put 0x5647 long MEMORY_FILE2
	put 0x800 short MEMORY_FILE2
	put BITS short MEMORY_FILE2
	put 2 short MEMORY_FILE2
	put 4089 short MEMORY_FILE2
	putDstring "fact" 4 MEMORY_FILE2
	put 4 long MEMORY_FILE2
	xmath SMP_LEN "SIZE * 2"
	put SMP_LEN long MEMORY_FILE2
	putDstring "data" 4 MEMORY_FILE2
	put SIZE long MEMORY_FILE2
	log MEMORY_FILE2 0 SIZE MEMORY_FILE
	
	get TMP_SZ asize MEMORY_FILE2
	
	putDstring "RIFF" 4 MEMORY_FILE3
	put TMP_SZ long MEMORY_FILE3
	log MEMORY_FILE3 0 TMP_SZ MEMORY_FILE2
	
	append
endfunction
Please note, that the resulting WAV file is pretty unplayable due to encoding differences between Intel DVI and Microsoft IMA ADPCM.
DeevDaRabbit
Posts: 6
Joined: Thu Jan 12, 2023 11:54 pm

Re: Space Invaders 1999 ZSNDWIN files

Post by DeevDaRabbit »

Unfortunately, most of the soundtrack consists of sequenced music which I guess must be played back in-engine and therefore cannot be converted over to a playable file.
Thank you for trying though.