Previous Thread
Next Thread
Print Thread
Page 1 of 9 1 2 3 4 5 6 7 8 9
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hello everyone, this is my first post here, I'm sorry if it's too long :-)
My name is Vagelis, I'm a romhacker and I mostly translate games to Greek. In some rare cases, except from altering the font, the text and the graphics, I have to change the sound as well. I've done it in Street Fighter II for the SNES and in Flight of the Amazon Queen that runs on SCUMMVM. In the past two months I've been translating Golden Axe to Greek. The translation is really finished and it's (technically) of top quality, but there is one more thing I'd like to do and that is to replace one of the sound samples. It's the one that says "welcome", number 65 if you want to play it with M1; all the others are screams or sound effects. I'm seeking for help here, as hopefully someone may know technical details.

First of all, let me tell you some things I have observed and tried.
The sample I want to replace is in the ROM file mpr-12384.ic6, luckily at the beginning.
By looking at the bytes there, I can understand that there is some kind of a header. It seems that each sample starts with FF 00 00 00 00 10 (and if that's absolute, there must be 20 samples in that ROM file). I'm not sure where the samples finish, if it's the next pair of FF FF bytes (most probably though). Before the FF 00 bytes (of the samples following others), there are some FF bytes (fillers?), most of the times followed by FF 00 5A A5 and then another FF 00 00 00 00 10 (the beginning of the next sample).
It also seems there are banks of samples, as well and that's because I can see that every 4000 bytes (hex), there is the start of a new sample, and also, before that, there are many FF bytes.
It makes me think if FF 00 5A A5 is something like a command. I'm not sure if it is really part of the previous sample, or something separate, between the previous and the next samples. It's not part of the next sample, that's for sure, because it exists at the end of some banks. Also, if I alter some bytes in the sample, in the game (in the service menu really), this affects the volume of the next 2-3 samples! After I play one that sounds loud then they also are loud again.
Another thing is that right after the bytes FF 00 00 00 00 10, there can be 53, 01 53, 09 53, 10 53, 0B 53, or 0C 53. Byte 53 is always present, but 6 or 7 bytes after the first FF, the offset varies by 1!
Anyway, these are just observations of the bytes. To tell you the truth, I could also check the equivalent ROMs of other Sega System 16B games, to find similarities or differences.

Except from looking at the bytes themselves, I installed Audacity and tried to extract the sound. This way I found out the type/encoding of the sound. It is Raw, VOX ADPCM, mono, 8000 Hz. If I select Import->Raw data and feed it with the whole ROM file, I'll be able to hear all the sounds. I have to cut the part of the first sample, but I'm not certain where to start and where to stop. Start at the beginning, after FF 00 00 00 00 10, after byte 53? Stop right before the FF 00 of the next sample, before the FF 00 5A A5, before the filling FFs?
Anyway, there is also something unfortunate: Audacity has a bad bug and doesn't export a raw VOX ADPCM, it throws an irrelevant error, see here, it happens to more people: https://www.reddit.com/r/audacity/comments/oh1fve/having_trouble_exporting_audio_to_raw/
I have managed to export a file, only two times! I'm not sure how, I think it worked only after a fresh install of Audacity and then running it as Administrator. I have tried old versions, as well as also installing FFmpeg.
This bug is making it extremely difficult for me to experiment...
I can tell you that the one file that Audacity produced, starts with FF 00 00 00 68 and the last bytes are FF FF FF C0 88 08 80 88. It's somewhat different...

One other thing I should say, is that a byte change on the original sample can corrupt it. The corrupted samples don't break the game, you just hear nothing or a click, but M1 throws an error and quits:
"ERROR: unable to load ROM mpr12384.a11
ROM load error, bailing"

Except from this, I'm wondering if it's possible to take advantage of the empty space, the FF bytes at the end of the banks, to add samples! If you could move the samples to different banks, you could take advantage of almost all the empty space. Even if you couldn't do that, the empty space at the end of the whole file would be enough for two samples that are bigger than the "welcome" sound. A "game over" voice would be fantastic. I'm not planning to do that yet, but if I manage to replace the first sample, I might experiment a little.

I know I can also look into the M1 and MAME source code, but I don't know where to start, and I program in C# and VB.NET, which makes it a little difficult for me.
Does anyone know any details that would help? Or even to point me to certain parts of the source code?

Btw, M1 is great! I only downloaded if because of this, but I'll be using it just to listen to some songs, for sure :-)

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Vag
I'm not sure where the samples finish, if it's the next pair of FF FF bytes (most probably though).
A small correction: Before the FF FF bytes, there is always 00, so the sounds probably finish at 00 FF and then there are more FF bytes...

Joined: Mar 2001
Posts: 17,258
Likes: 267
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,258
Likes: 267
You probably already know, but there's some info on the ROM format here: https://github.com/mamedev/mame/blob/master/src/devices/sound/upd7759.cpp

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hi R. Belmont, thanks for the reply!
I read it, but unfortunately there's much I didn't understand.
E.g. it says "The sample rom has a header at the beginning of the form nn 5a a5 69 55". Obviously, this has to do with bytes FF 00 5A A5, but I don't understand how. As there's no 5A A5 69 55 (that would mean master mode), it means slave mode, right?
For slave mode, it says: "The first command is always 0xFF. A second 0xFF marks the end of the sample and the engine stops. OTOH, there is a 0x00 at the end too. Go figure.".
I believe the 00 is necessary as the FF can be a random byte value? Few sounds do have FF somewhere in the middle...
So, the FF at the beginning means the beginning of the sample, and it ends with 00 FF.
I still don't understand what FF 00 5A A5 is, or why it's not always present. Or what byte 53 is, that's always there, or its offset being 6 or 7. I also don't understand the FF bytes near the end...

Today I spent hours, mostly distracted with "SEGA CRI ADX ADPCM" format, that I now believe is irrelevant (it's for Sega Dreamcast and later, I think).
Btw, Audacity has that bug that shows that error, but produces the file despite saying the opposite.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
I think that the long sequences of FF bytes are just the default state of the ROM - I read somewhere that the ROM programmer does not have to write to these areas if FF is set, so it is quicker to burn the ROM. I have seen ROMs for other games that do this also.

From what I can tell, it looks like the string FF 00 00 00 00 10 indicates the start of the sample and FF 00 (or FF 00 5A A5) indicates the end, and FF is used to pad the sample to the correct length? But the last sample in the ROM does not have FF 00 or 5A A5 at the end. I tried overwriting the 5A A5 with random data and the samples still play.

I also tried copying the "welcome" sample and pasting it over the very last sample (this is the sample that plays when the very first enemy is killed) and that works, so I think you could use whatever space is available in the ROM if you wanted to replace the "welcome" sample with a longer version, as long as it is padded to the correct length and the ROM is the same size (131,072 bytes). I tried exporting some audio from Audacity but the values look wrong and the game won't play the audio.

Last edited by Dodg; 10/27/24 05:48 PM.
Joined: Mar 2001
Posts: 17,258
Likes: 267
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,258
Likes: 267
There are a lot of versions of ADPCM, all incompatible. I don't know if any existing tools generate data in the format the uPD7759 uses.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
The MAME driver seems to be the most-often quoted source of information about the uPD7759, so perhaps it would be possible to build a copy of MAME that outputs some debug data from that driver? I would do this myself but my Mac is probably too old to build MAME now...

I did find a "user's manual" for an earlier chipset but it says that you were supposed to send an audio cassette to NEC and they would then send you a floppy disk with the ROM code. So, a nice scalable solution. That might explain why there are lots of datasheets available but no ROM programming examples.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Thank you both for your replies :-)

Originally Posted by Dodg
I think that the long sequences of FF bytes are just the default state of the ROM - I read somewhere that the ROM programmer does not have to write to these areas if FF is set, so it is quicker to burn the ROM. I have seen ROMs for other games that do this also.
That's really interesting! It's like the ROM chip is not even written there. This will give me a fresh look, as I'm trying to figure out how they work.

Originally Posted by Dodg
From what I can tell, it looks like the string FF 00 00 00 00 10 indicates the start of the sample and FF 00 (or FF 00 5A A5) indicates the end, and FF is used to pad the sample to the correct length? But the last sample in the ROM does not have FF 00 or 5A A5 at the end. I tried overwriting the 5A A5 with random data and the samples still play.
I thought it was FF 00 00 00 00 10, but maybe it's only FF 00 and the next bytes happen to be the same in these sounds. If I have time today, I will try to check the equivalent files from other System 16B games.
The end is indicated by 00 FF (FF 00 is probably a typo?). FF 00 5A A5 may be or may not be part of the sound file. Most sounds have it at the end, but not all. Today I will experiment with this, even try to remove it.


Originally Posted by R. Belmont
There are a lot of versions of ADPCM, all incompatible.
Originally Posted by R. Belmont
I don't know if any existing tools generate data in the format the uPD7759 uses.
It seems that at least the main part is compatible with VOX ADPCM, as I can hear the sound in Audacity, if I import the raw data as that. My intention is to copy-paste part of the new VOX ADPCM file over part of the old one. If it's raw data, it should work. Raw PCM has values, it would work - but ADPCM has value differences, and probably that's why it breaks. Except from any bytes that may not be sound, but some kind of command, the first byte I copy has to be changed, really. Audacity can save an ADPCM sound as text, here's a sample:
-25
-1159
2620
1111
654
1900
2278
561
-1624
-1908
1965
So, depending on the first number I paste, maybe the value goes out of bounds. If that's true, it could happen with the first byte after the bytes I paste, as well. I mean, the format may be compatible, but not the values...

Originally Posted by Dodg
I did find a "user's manual" for an earlier chipset but it says that you were supposed to send an audio cassette to NEC and they would then send you a floppy disk with the ROM code. So, a nice scalable solution. That might explain why there are lots of datasheets available but no ROM programming examples.
I found programs (and code) that produce the SEGA CRI ADX ADPCM format, only that's for later Sega games, for Dreamcast, Playstation, PC; but at least that gives me some hope that I'll make it with the format in Golden Axe :-)


Originally Posted by Dodg
The MAME driver seems to be the most-often quoted source of information about the uPD7759, so perhaps it would be possible to build a copy of MAME that outputs some debug data from that driver? I would do this myself but my Mac is probably too old to build MAME now...

I did find a "user's manual" for an earlier chipset but it says that you were supposed to send an audio cassette to NEC and they would then send you a floppy disk with the ROM code. So, a nice scalable solution. That might explain why there are lots of datasheets available but no ROM programming examples.

Well, I haven't ever built MAME, so I won't try it for now. But maybe I should try with M1, to see what it checks and doesn't like, and throws that error. Maybe with trial and error I could manually correct the bytes that break it.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
Well, I haven't ever built MAME, so I won't try it for now. But maybe I should try with M1, to see what it checks and doesn't like, and throws that error. Maybe with trial and error I could manually correct the bytes that break it.

Yes, that is a good option if you can build M1. I will look at my copy of M1 if I have some time tomorrow. I think 53 may be the code to play the next 128 bytes (256 nibbles) because this appears at regular intervals throughout the data. There is a bitwise operation using 0x53 in the driver code which is used to calculate the sample frequency, and the calculation works out to 8000 (Hz).

Last edited by Dodg; 10/28/24 08:03 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
I think 53 may be the code to play the next 128 bytes (256 nibbles) because this appears at regular intervals throughout the data.
That's a great observation, thanks! :-)))

As the sound can be heard normally after you import the file to Audacity, I had made the assumption that there must be some kind of a header, then you have the raw data and then maybe some bytes at the end. Maybe Audacity takes the 53 bytes for samples, sound data, but they pass unnoticed when you hear the sound.
It seems that what's between the 53 bytes, is indeed raw sound data. I checked the 53 bytes one by one, and near the end, where 53 was expected, there's 93, followed by a number of bytes, before the 00FF. These bytes look similar to the previous raw sound data, I guess they are also raw sound data. I checked the next sounds, and the number of these bytes varies (it's 57, 12, 122, 69 and so on). My guess is that 53 means it should read the next 128 bytes, like you said, but as the sound can have any length and the total number of raw bytes doesn't have to be divided by 128, the last group can have a different number of bytes.
The first sound though has 190 bytes after 93, which means that if it was that simple, it would have byte 53 instead and then byte 93, followed by 62 bytes (190-128). But it doesn't! It has 93, then 66 bytes, then 93 again, then 67 bytes, then 93 again... I don't know if the 2nd and 3rd 93 bytes mean something, or if it's a coincidence.
I will have to experiment with the data. I won't have much time today, till late in the evening, but I think we're getting very close now :-)

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
[quote=Dodg]As the sound can be heard normally after you import the file to Audacity, I had made the assumption that there must be some kind of a header, then you have the raw data and then maybe some bytes at the end. Maybe Audacity takes the 53 bytes for samples, sound data, but they pass unnoticed when you hear the sound.

Audacity is able to "guess" the format just by looking at the data - there is no header in the ROM, Audacity just looks at the sequence of bytes and see if they follow a recognised pattern. So, I think it is ignoring any bytes that do not match a pattern. If you look at the Audacity source code you will see it has some clever logic in it to identify the format.

I noticed that the 93 is significant, I think it is probably used for a similar purpose to 53. However, 93 is a valid audio data value so it could be contained inside any block of 128 bytes. In my M1 debug log, when I play the "Welcome" sample only the last three 93 values triggered an action. The very last 93 value was also preceded by 08 which did something?

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
It's the same with 53, it is a valid audio data value. So I guess when values 53 or 93 are inside the block of the 128 bytes that follow 53, they are considered audio data values; if they are read where expected, right after the 128 bytes, then they must be considered commands.
There are 53 bytes that are indeed audio data values, e.g. one is at offset F0. That's why I'm not sure if the 2nd and 3rd 93 bytes mean something, or if it's a coincidence. Maybe 93 byte means "read audio data values till 00 FF" (hopefully).

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
A promising little update: I can now hear the new sound in the game!
It's too low and has hissing, but I believe that may have to do with the file Audacity created. I will have to try with different files or formats.
The main idea was this: I took the new sound (raw VOX ADPCM) and I inserted the 53 byte at the beginning and then after every 128 bytes. Instead of the last 53 byte, I inserted a 93 byte.
If I add FF 00 5A A5 at the beginning, the sound still plays.
Unfortunately I would have to move the following sounds, if I wanted to insert a longer sound. For testing, I can insert a longer sound, of course it overlaps with the second sound and the second sound is not heard. But even if I can't move the following sounds, I can change the tempo (and length) of the sound before I convert it, to take advantage of as many bytes as possible :-)

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Good job!

You could try using SoX as this has some different export options. I tried to convert a WAV file but could not get anything to sound right when I manually copied the bytes into the ROM data.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hello everyone :-)
There was almost no time at all, the previous week... Starting from today, I'm back on this, and I'm hoping to understand the problem.

First, here's something interesting I found online: http://www.bitsavers.org/components/nec/_dataBooks/1989_DSP_and_Speech_Products_Data_Book.pdf
NEC used to sell a PC add-on card, called "NV-300 System µPD775X Family Speech Analysis Tool" (or "Speech Analysis System"), that would allow you to digitize the sound, edit it, trim it, filter it, play it, convert it to ADPCM, then back to PCM (for evaluation), and finally "convert the ADPCM data to µPD775X HEX file" for writing to the ROM.
You can search the pdf with "NV-300" to see details, and a photo of the card.
In page 1-35, it shows the chips that NV-300 would create sounds for:
µPD7755C/µPD7755G
µPD7756C/µPD7756G/µPD77P56C/µPD77P56G
µPD7757C/µPD7757G
µPD7759C/µPD7759GC
In page 4-29, 4-30 and 4-31 you can see the product details, including a photo and two diagrams.
In page 4-33 and 4-34, you can see another peripheral, called "EB-7759 µPD775X Demonstration and Evaluation Box", that was used for evaluation of the sounds. It could be used as a stand-alone unit, or be connected to a PC, or "be plugged into the target hardware to emulate the masked ROM parts".
A newer version of NV-300 is NV-301, and there is also a newer model, NV-310.

I found all that very interesting, but not very helpful, with the file :-}

I have some new observations:
1. Using sox, I created 8 different variations of ADPCM sound. If I look at the bytes with a hex editor, I can see that most bytes are the same, but there are differences. I tried them all, and in the game, the sound the same.
2. I found this page: https://rutube.ru/video/87049aff131218a5d9bc3122fd866cc9/ that has a link to a zip file with voice ROM dumps (that are not for a System 16 game, but a device called "AlliedSignal Mk VII Warning Computer").
In Golden Axe, I could see similar repeating bytes near the beginning and the end of the sound files, like many 11 bytes. I don't know if they are sound data, or if they are some kind of command bytes. I see that they are common in these dumps as well. E.g. the first bytes in a sound are:
00 FF 00 01 53 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 12 11 11 11 11 11 11 1A 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 12 12 31 CB 46 4D EA 24 3A 92 51 CC B2 28 BB 93 43
3. I have tried pasting the new ADPCM data after all these 11s, over the original sound file, but the result sounds the same, always.
4. I have inserted sounds from these dumps I found and they sound perfectly, in the game, whether they have 11s, or not. This means I can use sounds from other games, which is good, just not what I currently want.
5. Maybe the first two bytes (FF 00) are not necessary, as the sounds in that dump doesn't have them! I'm thinking they are a kind of command that maybe initializes something.
6. After some attempts, I have noticed a side-effect. After I play the sound, the sound volume is reduced. If I play it again, it's reduced even more. If I play the next sounds, they are also affected. Sound 04, the fifth one, sounds loud again and restores the volume level for all the sounds.
7. I have found M1 written in C#: https://www.codeproject.com/Tips/646359/M1-NET-Decrypt-Arcade-Audio, maybe it will help me read the M1 code :-)
8. I have found a thesis with a title "Subjective tests on 32 kbps CVSDM and ADPCM codecs for business satellite communication systems": https://openresearch.surrey.ac.uk/v...ePid=13140690740002346&download=true
It has a chapter called ADPCM CODECS SOFTWARE IMPLEMENTATION, with these two parts:
The NEC ADPCM encoder algorithm implementation (page 204, 216 in the pdf)
The NEC ADPCM decoder algorithm implementation (page 219, 231 in the pdf)
9. If I convert a sound to wav and then back to ADPCM (and take care of the 53 bytes), the original and the new ADPCM files have big parts that are the same, and small parts that differ. The same happens with different variations of ADPCM. I'm almost sure that the correct ADPCM variation isn't VOX, or IMA, but NEC ADPCM. Probably Audacity can decode NEC ADPCM and that's the reason it produces a clear wav file.

I believe the only way would be to implement the "NEC ADPCM encoder algorithm", as it's in the previous pdf. All other ADPCM variations will have noise and hissing, because too many bytes are different, even though the voice can be heard because of the common bytes. I will keep searching in the Internet for a possible implementation, but I don't think there is one.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Good research there smile When I have time I will read the documents.

It does appear that NEC used its own ADPCM format. Maybe the chip was designed to take advantage of some of NEC's optimizations to improve performance, reduce cost or allow inline bytes to control the chip? Audacity uses a rule-based system to decode raw ADPCM data so NEC's implementation should be fairly close to the others but with extra bytes to control the chip. Also, the documentation I have read says that NEC's implementation uses a 9-bit algorithm rather than 8-bit? They also called their implementation "repeated phoneme ADPCM".

I'm not sure that M1.NET supports Golden Axe so maybe it will not help? I think it would be easier for you to use the M1 source (the most recent version of the source code is available on this forum somewhere) if you can build it. The latest MAME driver for the chip has slightly different code to the version in M1, but it is very similar. If you can understand how the decoding works and compare it to the information in the thesis, it should be possible to understand how the encoding works too.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
It seems the file is encoded in 4-bit APCM, and there's a conversion to 9-bit by the chip, when the sound is to be decoded. That was confusing, I searched for 9-bit APCM, but couldn't find any programs that support that.

One thing I could try, is the M1 code. I may check the C# version, but first I will search some more, in case I find an existing solution.
I'm also wondering what would happen if I find out which are the common bytes in VOX and in IDA ADPCM (in a new sound), because most probably they would also be common in NEC ADPCM, and then combine these with the original sound's bytes that differ. Obviously I could do that only if the new and the original sounds have the same number of bytes, but that's doable, if I change the duration of the new sound, before creating the ADPCM files.
That's a lot of work to do manually, even for one file; maybe it would be easier to write a program that compares the new VOX ADPCM and IDA ADPCM, marks the bytes that are common, then replace only these bytes in the original NEC ADPCM file with the data of the new VOX ADPCM. It doesn't have much chance, but I'm curious, maybe the noise will be much less then.

Edit:
I uploaded the pdf (with the algorithm) to ChatGPT (it has a "Data Analyst" GPT now) and asked it if it can write code according to the algorithm in page 204.
It replied that the listing of the NEC ADPCM Encoder program is also included! :-P
Haha, the pdf was so big, written in a typewriter and scanned, that I missed it!
Anyway, the listing for the encoder is in page 301 (316 in the pdf) and for the decoder, in page 314 (326 in the pdf).

Last edited by Vag; 11/04/24 04:53 PM.
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Although it is not about the NEC chip this ADPCM encoder/decoder guide from Microchip has some information that I found helpful to explain the ADPCM process at a basic level with some code examples.

This does not add much information, but:

I noticed in my M1 debug log when I play the samples that the 53 byte also sets a frequency value of 0x13 - the 0x13 is calculated using a bitmask. Based on the information in the MAME driver, this gives a sample rate of 8000Hz because the 0x13 frequency value is converted to decimal + 1 (which is 19 + 1 = 20) and the sample rate is then calculated by 640000 / 4 / 20 = 8000.

There is also the bit rate to consider. I am not sure how this is determined, but it might explain why your samples are noisy. Maybe the bit rate is not correct?

EDIT: You saw in the thesis that the assembly code is meant for the PC-8000 computer? Now that you have an algorithm, it should be possible to rewrite the assembly code in C or another language.

Last edited by Dodg; 11/04/24 05:58 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
There is also the bit rate to consider. I am not sure how this is determined, but it might explain why your samples are noisy. Maybe the bit rate is not correct?
I thought that myself at first. But the bit rate is determined by the bit depth and the sampling frequency. The frequency is 8000 Hz, the bit depth is 4-bit, so the bit rate is 32 kbps. It's not a separate setting.

Originally Posted by Dodg
You saw in the thesis that the assembly code is meant for the PC-8000 computer? Now that you have an algorithm, it should be possible to rewrite the assembly code in C or another language.
Well, there are two options. The one is to directly compile that assembly code for the PC-8000, and the second one is to convert it to another language (I would prefer C#).
The first option means I have to look for an emulator (I have never used one for the PC-8000, but there are many), and also an existing tool, to compile the assembly code. That would be straightforward and it would work out of the box, without any bugs. But I have to find tools for that. We'll see...
The second option is the best if you want to be able to replace other sounds in the future. It will be more time-consuming for sure, but the result would be much better. A Windows program, preferably a command line program.
I have a friend who's willing to assist me, his name is ChatGPT, we'll try the PC-8000 solution first :-/

Edit: Maybe it's a good opportunity to take a look at the games of PC-8000! Maybe I should also translate a PC-8000 game, as well :-)

Last edited by Vag; 11/04/24 08:49 PM.
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
I thought that myself at first. But the bit rate is determined by the bit depth and the sampling frequency. The frequency is 8000 Hz, the bit depth is 4-bit, so the bit rate is 32 kbps. It's not a separate setting.

Yes, I am stupid and forgot that smirk Do you think the noise is due to incorrect quantization values when the audio is encoded?

MAME supports the PC-8801 and there is a list of floppy disk images here which includes CP/M (there are no images for download but you can find out what the filenames are and search for them elsewhere). A long time ago I built QUASI88 from source and it works fine, although I don't know if it can fully emulate the PC-8801. I think it would be easier to rewrite the assembly code in C or C# although that would not be as authentic as writing the assembly using the original computer!

Last edited by Dodg; 11/04/24 11:21 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Oh, we both know you're brilliant! That observation that 53 is repeating every 129 bytes and everything you wrote, proves it ;-)

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
We will see how brilliant I am if I can manage to translate the assembly code into C wink If I am able to help at all, I am happy with that. It is good that there are people like you working hard to translate games into Greek.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
OMG, if you could do that, it would be the best! I only have a basic knowledge of ASM, mostly gained from romhacking, and I would rely on ChatGPT's help for the most part.
Do you want me to prepare the code as text? Unfortunately Chat GPT can't read it properly from the PDF or from a screenshot...

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
The PDF is fine thanks. I think the assembly code is for the μPD7720 DSP though so that makes things difficult - there are lots of opcodes and flags that have nothing to do with the Z80, so you would cross-compile the code on the PC and write it to the chip on the evaluation unit (I think). Still, I will try and maybe I can learn enough about how the algorithm works. I have found a datasheet with a list of opcodes at least. Do not expect any results soon! I think this also means that trying to write the code in an emulator may not be possible without the cross-compiler software.

If you do see any reference to the μPD7720 for arcade games please let me know. I found some references to a modified version of it being used in SNES cartridges.

Last edited by Dodg; 11/05/24 02:07 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
Do not expect any results soon!
The greatest virtue in romhacking is patience! I've done it with many games, but especially with Golden Axe, I spent 2 days just to draw 1 pixel! I spent a week just to center some text! Sometimes you're desperate because you have spent days and you have accomplished nothing, but then you manage to do it, and the delight is compensating. When I look back at some of my 20yo translations, I feel bad that I didn't perfect that one pixel or tile in the graphics, that took me days without any progress.
In the meanwhile, I will try to find how to move the sounds in the ROM. The first bank contains 6 sounds. At the end of the bank, there are 2784 FF bytes! If I can move the five sounds after the first one near the end of the bank, the space for the first sound will be much bigger.
If I manage to do that, it will be the first step to find a away to add a sound, not just replace an existing one.

Originally Posted by Dodg
If you do see any reference to the μPD7720 for arcade games please let me know. I found some references to a modified version of it being used in SNES cartridges.
I'll try :-)
I don't know if this helps at all: https://www.oguchi-rd.com/7720/%C2%B5PD7720%20Design%20Manual.pdf

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
I don't know if this helps at all: https://www.oguchi-rd.com/7720/%C2%B5PD7720%20Design%20Manual.pdf

Yes, that is very helpful thanks. I am going to study the code from this ADPCM encoder/decoder first and once I can understand the basic principles, I can will then look at the µPD7720 code.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Now, here's not the right place to report MAME bugs, but I just found one - I just registered with mametesters, I'll report the bug there.
If you go to the service menu to play the sounds (press F2 and then navigate), the sounds (and the songs) are played two times, with a small delay, and the result is an ugly sound you can't hear properly. I had a very hard time recognizing "welcome", for example. The sounds are heard properly in the game, the problem is only in the service menu. I wasn't sure if that was a bug in the game or in MAME. But now I saw that if I start MAME in debug mode, all the sounds and the songs play correctly!
Maybe the sound is played twice (for stereo), and there's a delay that shouldn't be there? I have no idea.
The funny thing is that I first started using M1 just to be able to hear the "welcome" sound clearly :-D

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
What version of MAME are you using? It works fine for me in MAME 0261?

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I don't have the latest version, but not a very old one anyway. I have 0.267 and I see that the latest is 0.271. But as you say it's fine in 0.261, I don't think it's the version.
By the way, I have to run MAME from the command prompt, because else, it won't run modified ROMs.
Like this:
mame goldnaxe -video gdi
or like this (which sounds correctly):
mame goldnaxe -video gdi -debug
Also, I have Windows 10 64-bit.

Last edited by Vag; 11/06/24 02:31 PM.
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
If you run the game in a window (without using the debug mode) like this

mame goldnaxe -video gdi -window

is the sound still wrong? You could also try using a different video mode if your computer supports it. Also check the frame rate in case something strange is happening in test mode that is causing the game to run too fast or too slow.

Last edited by Dodg; 11/06/24 03:42 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Yes, the problem is still there. I had tried windowed mode with Alt+Enter, now I tried it with -window. Also, MAME only works with -video gdi for me.
The frame rate and speed are normal. Also, if I press Insert (for fast speed), the sound is heard too fast to be sure :-}
Mind that the sounds are all OK during attract mode or gameplay. The problem happens only in the service menu. I hear something like "welwelcomecome...", but it's not always exactly the same, like the delay differs a little, every time. If I select to hear a song, the problem persists throughout the song, I hear it twice, with a small delay.
I just noticed something funny, if I press Alt+Tab (to select another window), the sound starts playing because Alt is the second P1 button, and I hear it correctly. It seems the sound starts playing, and because the window goes to the background, it doesn't start playing for a second time, so it's heard correctly.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
I don't know what the MAME debugger does that is different to "normal" mode. All I can suggest is try either an earlier version or a later version of MAME and see if the problem is still there. I have MAME 0251 on my machine as well and it works ok. Maybe it is a sound driver issue?

Joined: Feb 2004
Posts: 2,625
Likes: 332
Very Senior Member
Very Senior Member
Joined: Feb 2004
Posts: 2,625
Likes: 332
That sounds a lot like MAME not running at full speed when using DirectSound. Did you hit F11 so you can see the emulation speed when this is happening? Bitmap output is expensive with GDI video, so if you fast forward it will run faster because it’s skipping that for most of the frames.

I just checked and it works fine in the latest version of MAME in full-screen.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Just to rule out another possibility, does this happen on a unmodified copy of the ROMs as well as your modified versions?

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
Just to rule out another possibility, does this happen on a unmodified copy of the ROMs as well as your modified versions?
Yes, it's with any version, both sounds and songs.

Originally Posted by Vas Crabb
That sounds a lot like MAME not running at full speed when using DirectSound.
That's it! I had to skip 4 frames, because the speed was at 65-70%, and it sounds normal!
My PC is a little old, it has an Intel Core2 Quad CPU Q6600 @2.40GHz and 8GB RAM.
All that time, I thought the game was running at 100% speed :-O

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
I have not made much progress, so I am going to try and explain the ADPCM format as I understand it and if I am wrong please correct me:

ADPCM takes an audio signal value and then tries to predict what the next values will be based on previous values. It then stores the difference between the signal values rather than storing the next value as-is, which reduces the number of bytes needed to represent the signal value. ADPCM can adjust the amount the signal moves (+ or -) to respond to fast or slow changes in the signal, which is helpful because it only has a small number of discrete steps to represent the signal (16) but they can be spread over a wider or narrower range to suit the rate of change in the signal.

I guessed that 0x53 tells the chip to treat the next 128 bytes (256 nibbles) as audio data. Is the next byte (2 nibbles) following 0x53 then used to calculate the signal position from 0 or a previously stored value? Assuming each nibble represents a signed value, this means that they can represent values between -8 to +7. We have two different values to get - the step size, and the movement within that range. This makes me think that each pair of nibbles must be used to encode both of these values unless there is some way to use the previous saved value with the first nibble to set both values, then the second nibble uses the first nibble, etc. This would make sense because the step look-up table has 256 values in it, and therefore only needs 1 byte to retrieve a value from the table. Some ADPCM formats use a header to set a step size every X number of bytes.

The look-up table for the steps used by the NEC chip appears to be different to the OKI look-up table, so I think this is why it is proving difficult to use existing tools to convert WAV files to the NEC format. It is also possible that the OKI values are using values outside the range that the NEC chip can use, generating random noise rather than the expected sounds.

I am going to continue looking at the driver in M1 and I will hopefully have some answers soon.

Last edited by Dodg; 11/10/24 08:40 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
I have not made much progress
Don't be discouraged, this is very complicated and too hard anyway. Sometimes I'm totally disappointed when in a dead end, but sometimes a new idea comes up.
You may keep trying if you want, but if you don't have the time, never mind :-) Maybe a future, much smarter ChatGPT could do it by itself :-)

Originally Posted by Dodg
I have not made much progress
Me neither!
I have found four groups with four memory addresses that change when you select a sound or when you play a sound, that they are repeated 4 times, so it's 16 addresses.
In each group, one of these can take the values 00 or 0D or 35, for songs, sound effects and voices. The voices are the the ADPCM sounds.
Another one can take values 00-13, which are the ADPCM sound IDs and they are also shown like this in the service menu. Near that byte, there are equivalent bytes for songs and sound effects (but as I'm not trying to change any of these, I won't deal with them).
There is one more, that works in the same way, but the values it takes are 35-48. That's because 00-13 are the voices IDs are 00-13, but 00-48 are all the sounds IDs, including the songs.
All the above bytes change as you select which sound you want to play (in the service menu). There is one more, that changes as you play the sound. I don't know yet if that byte defines which sound will be heard, or if it just shows which sound is being played. It takes values 00-48, for any type of sounds. So, for voice 00, that byte would be 35, for byte 13, it would be 48.
I have yet to find the pointers to the sounds, I don't know where to look. In order to be able to add new sounds, I will also have to find how to change (the above) 13 to 14 and 48 to 49.
I don't have much time lately, but I'll keep on looking.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
To find out when music or samples are triggered, you could use the MAME debugger and look for writes to the soundlatch memory address. This will tell you which instructions in the main CPU code are used to trigger the sounds.

If there is a single byte with a value that changes whenever new music or a new sound effect is played, that might be the soundlatch. You can compare the memory address you found with the code in the MAME driver for Golden Axe to see if the address matches. So, the main CPU writes a byte to the sound latch memory address and the sound CPU (Z80) plays the music or sample. The epr-12390.ic8 ROM has Z80 code in it at the start as well as data (for playing the music?) and these instructions and data are then combined in memory with the ADPCM samples in the mpr-12384.ic6 ROM but the sample data is accessed at a higher memory address. So, the Z80 must be able to look at the address in the sound latch and know whether it is supposed to play music or a sample because it has to send instructions to the music chip or the ADPCM chip. I am not sure how it does this.

When I have time I will keep trying to understand the ADPCM code... at least I am learning something smirk

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
I am learning something smirk
People tell me I'm losing my time with romhacking, but it's exactly what you said!

I know about epr-12390.ic8, and I have been comparing trace files. But I don't just want to trigger a sound (that's a very important part of course), but to also change the service menu, so that you can select any new sounds. I've also looked at how the memory changes, that's how I found the 16 bytes that change, depending on the sound selection.

In fact, there are five things I would like to do:
1. Convert sounds to NEC ADPCM, so I can replace the "welcome" sound.
2. Find the sound pointers and be able to move them around in the ROM, to take advantage of the available space.
3. Add new sounds.
4. Play the sounds in the game.
5. Adjust the service menu so it shows the new sounds.

Obviously that's optimal, I'll be more than happy with replacing a sound :-)

Joined: Mar 2001
Posts: 17,258
Likes: 267
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,258
Likes: 267
Changing the service menu and playing different sounds in the game is going to be much more involved since that lives on the 68000 side. Most Golden Axe sets are encrypted by a dynamic scheme and would be very difficult to change.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
If one of the unencrypted bootlegs was used, it should be possible though?

Joined: Mar 2001
Posts: 17,258
Likes: 267
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,258
Likes: 267
Possible, but still complicated.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I have already made many changes (to the main set), I had no encryption problems. Previously I attempted to translate Space Harrier and it's impossible to change the text without breaking the game.

Here are some screenshots, by the way; the third is the sound submenu in the service menu.
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]

Except from the sound, I only have to center a certain text (see the last image), and find the new checksum for the checksum check in the service menu (where it checks the memory chips really).

Edit: I have edited the font, the text, background/foreground graphics, a sprite (the "GO!" sign), some palettes, and graphics tilemaps, of course. I also added some new assembly code in the translation (it has to do with some strings in the service menu). After seeing that problem with Space Harrier, which is an intentional type of protection by Sega, I first checked Golden Axe thoroughly, before starting the translation. I can't be 100% sure that all other System 16 games can be translated/hacked easily.

Last edited by Vag; 11/11/24 08:04 PM.
1 member likes this: Dodg
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Some very nice work there smile Good job!

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Just some more details about the rom format while I am looking:

At certain points in the rom, the 0x93 byte is used to tell the chip to play the next X number of bytes, and the byte following that tells the chip how many nibbles to play. At rom location 0xEE7 byte 0x93 is followed by 0x81 (129 in decimal) and +1 is added to this value to equal 130. This tells the chip to play the next 130 nibbles (65 bytes). The next time 0x93 is used again is 65 bytes later, so this means that this might be correct.

There is also another command used to play X number of nibbles but repeat them Y times. This is a 3 byte long command. I haven't checked if it's used in the rom yet.

In the game, the Z80 memory location 0xE800 is the sound latch byte (I think). 0x9C is the coin-up sound, 0x90 and 0x93 are used for the axe swinging sounds, 0x54 is the sound sample for the first enemy when they are killed, 0x53 is the sound sample for the second enemy when they are killed, etc. If these values are converted to decimal they will play the correct sound in M1, for example ./m1 goldnaxe 156 will play the coin-up sound.

On the main CPU, memory location 0x00FFECFC appears to be where the same byte is also written to. In the MAME debugger I did this

wp 00FFECFC,1,w,wpdata,{ printf "Value is %08X\n",wpdata ; g }

and I get the correct values when the sounds are played.

Last edited by Dodg; 11/12/24 12:06 AM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
Some very nice work there smile Good job!
Thank you! :-)

Originally Posted by Dodg
At certain points in the rom, the 0x93 byte is used to tell the chip to play the next X number of bytes, and the byte following that tells the chip how many nibbles to play. At rom location 0xEE7 byte 0x93 is followed by 0x81 (129 in decimal) and +1 is added to this value to equal 130. This tells the chip to play the next 130 nibbles (65 bytes). The next time 0x93 is used again is 65 bytes later, so this means that this might be correct.
That's so great!
If there's no solution with the NEC ADPCM encoding, I may add the sound as a different ADPCM variation (with noise). At least these bytes will be correct!
Did you see that in the assembly code, or did you see the bytes in the sound file?

Originally Posted by Dodg
In the game, the Z80 memory location 0xE800 is the sound latch byte (I think). 0x9C is the coin-up sound, 0x90 and 0x93 are used for the axe swinging sounds, 0x54 is the sound sample for the first enemy when they are killed, 0x53 is the sound sample for the second enemy when they are killed, etc. If these values are converted to decimal they will play the correct sound in M1, for example ./m1 goldnaxe 156 will play the coin-up sound.
Originally Posted by Dodg
On the main CPU, memory location 0x00FFECFC appears to be where the same byte is also written to. In the MAME debugger I did this
wp 00FFECFC,1,w,wpdata,{ printf "Value is %08X\n",wpdata ; g }
and I get the correct values when the sounds are played.
Oh yes!!!
At FFECFC, FF00 stops the sound and 00xx starts the sound with id xx (including songs). When you start a sound, FF00 is first written, in case another sound was still playing, and then 00xx is written. When the sound ends, FF00 is written again. As there were 4 sets of similar values near that memory area, I checked the other possible addresses (FFACFC, FF6CFC, FF2CFC) but they are irrelevant (which is logical, but I had to make sure).

FF00 stops the sound and is also at the beginning of the Golden Axe sounds, but not at the other sounds I downloaded. I don't think that's a coincidence :-)
Maybe that specific FF 00 is written at FFECFC. That means that in the sounds, FF 00 is not really indicating the beginning of the file, but the bytes at the beginning of the file are commands (not a header), up to byte 53, that means that the following 128 bytes are data. Similarly, after the last 93 and the following data bytes, the next bytes should also be commands. 00 FF is the end of the sound data, but maybe it continues reading the next bytes, that are commands. Maybe FF doesn't do anything, but then you (usually) have FF 00 5A A5. So you have FF 00 again, which really makes the program stop the sound, and that's the next FF 00 that is written at FFECFC. 5A A5 must also be a command (or two commands). I don't think it's the end of the file as it's not always present.

When I have time, I will try to insert code that plays a sound when the GreekRoms logo shows up whole (it's where the FBI message was). Of course I can't really use it until I can add new sounds.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
The 0xFF00 value may be a coincidence, because the main CPU does not talk to the ADPCM chip directly but sends commands to the Z80. Because the Z80 is 8-bit, I think it will only see the lower byte so it might just see 0x00 then 0x9C instead of 0xFF00 then 0x009C. If the sound chips receive a play command when they are already playing, I think they will just restart playback - the Z80 might not need to tell the sound chip to stop playing first. Maybe the 0x00 is needed to tell the Z80 chip to reset a routine, or maybe it is only used by the main CPU and the Z80 doesn't care about it.

As you have said, in the ADPCM sound data the chip knows how many bytes to play, so anything after that is processed as commands. This is how it knows not to stop playing if it sees 0x00 in the middle of the 128 bytes of data, so it doesn't try to process it as a command and stop the playback. For the welcome sample, all of the bytes up to the first 0x53 trigger commands. The first 0xFF is significant, but the other bytes do not appear to do anything even though they trigger a command on the chip. I still have no idea what the 5A A5 sequence does because the ADPCM chip never reads that data (not in M1 anyway) and no other data is read after 0x00.

So, I need to write a Lua script to try and manually trigger a sound to be played. I will also use the MAME debugger to see what data is written to the soundlatch.

Last edited by Dodg; 11/12/24 11:19 AM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hey Dodg, of course you were right about location FFECFC, thank you for it!
I am now writing a value there, and a sound is heard.

There's a loop that shows or hides the screen, e.g. when the program starts.
I want to play a sound when the GreekRoms logo (the FBI logo in the original) is shown. D6 becomes zero then, but that also happens when the logo is hidden again, or in all other cases the screen does the same effect. The first time the game loads and the logo is fully shown, A6 is zero.
E.g. for the coin-up sound (156 - 9C):

In address 1A5C (which is inside the loop), I replace these three commands D444D0C5361F with 4EF900002E0C (a JMP to 2E0C, but Ι may change this address).
There is plenty of empty space there, so I add these:

D444D0C5361F (the commands I had replaced)
4A86 (check if D6 is 0)
6610 (if not, go to last command)
BC8E (check if A6 equals D6, which is 0)
660C (if not, go to last command)
2C7C00FFECFC (write FFECFC to A6)
1CBC009C (write the sound id, 9C, to A6 address)
4286 (restore A6 to zero)
4EF900001A62 (JMP back to where you were)

This works, but it doesn't do all I want. I didn't check properly, A6 is zero only the first time. I want the sound to be heard whenever the logo is shown by itself (and not when it's shown if you insert a coin).
I will also have to add one more check, because there is an on/off DIP switch setting for demo sounds.

If I put 00 instead of 9C there, no sound is heard and there are no side effects, it works. So, after I complete the code, I will just add it, with 00.
If I find a way to add new sounds, then I'll just update that one value :-)
I might then add two different sounds, one for the very first time, and another one for all the other times ;-)

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
How are you able to edit the 68000 code? It looks like the two ROMs are interleaved, but I thought that they are encrypted also?

I tried to write a Lua script to POKE a value into the soundlatch but it didn't work. I can read from the memory location, but I can't write to it. I had this problem with a different game but I can't remember how I solved the problem. Also, I tried to set a watchpoint for the soundlatch in the MAME debugger but it is never triggered so I can't see exactly what data is being written there. The watchpoint works fine for the main CPU, but not on the sound CPU.

Maybe it is a coincidence, but I noticed that the "Welcome" sample sounds like a slowed down version of the "Welcome" speech in Gauntlet II. I wonder if SEGA used the same hardware to generate the speech but then saved it as a sample instead.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
How are you able to edit the 68000 code? It looks like the two ROMs are interleaved.
I have written a tool for that, it's called Tile Mixer and it's here: https://www.romhacking.net/utilities/1707 or here: https://www.greekroms.net/files/programs/Tile%20mixer%20setup.zip.

You select two or more files that are interleaved and you can join them, or separate that file. You can change their order, if you want. You can also make it create a zip file (for MAME) with the new, joined file, or run a cmd command, like "C:\Romhacking\MAME\mame goldnaxe -autoframeskip -video gdi". You can also save all these selections and have it load them automatically. So, you just open that program and you press one button to join the ROMs and one more to run the game in MAME. You can even join two or three buttons together, so you only have to click on one instead of two :-)
Romhacking is too tedious sometimes, I had to make it as easier to use as possible, because during the two or three months that are needed to finish a hack or a translation, you do these tasks thousands of times!
And just for fun, after I wrote Tile Mixer in Greek and English, I translated it into 55 more languages (I used Google Translate, DeepL, and Microsoft Translator) :-o

Originally Posted by Dodg
I thought that they are encrypted also
No, luckily :-)

Originally Posted by Dodg
Maybe it is a coincidence, but I noticed that the "Welcome" sample sounds like a slowed down version of the "Welcome" speech in Gauntlet II. I wonder if SEGA used the same hardware to generate the speech but then saved it as a sample instead.
I wouldn't be surprised at all!
Enjoy:

Last edited by Vag; 11/13/24 03:03 PM.
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
That program looks good. I am on macOS so I will have to write my own tool - I am learning Python at the moment so I will try to write some code to do that (although it will be a command line tool and not look as nice as your program!). I can speak French as well as (some) Japanese if you need to check any translations - my Japanese is not great but I am ok with hiragana/katakana/basic kanji and can see if any automatic translations look wrong.

What I am doing now is writing some code to generate a very basic WAV file with a simple square wave. I can then use this file to see what values are generated by other ADPCM encoders, then I might be able to convert those encoders to use the look-up tables in the MAME driver.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
That program looks good. I am on macOS so I will have to write my own tool - I am learning Python at the moment so I will try to write some code to do that (although it will be a command line tool and not look as nice as your program!)
At some point I had found one or two other programs that join and separate ROMs (interleaved files). There has to be one for macOS, it's essential for arcade ROM hacking. I always thought that hex editors should also support something like that (even though that wouldn't help a lot with graphics editing, only hex editing).
If you write such a program, just make it so that you can change the order of the files if you want. It doesn't need to support more than two interleaved files, it's almost always two...
As for the language, never mind, I will refresh all texts with the next version anyway (because of new texts and of probably changing the translation file format), and I suppose that they will be of much better quality, as the AIs are getting smarter.

Originally Posted by Dodg
What I am doing now is writing some code to generate a very basic WAV file with a simple square wave. I can then use this file to see what values are generated by other ADPCM encoders, then I might be able to convert those encoders to use the look-up tables in the MAME driver.
That sounds great! It is probably a way to create sounds with no or much less noise, even though you won't use the same algorithm. I believe it's feasible and probably easier than implementing the NEC ADPCM algorithm from that thesis.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
It is probably a way to create sounds with no or much less noise, even though you won't use the same algorithm. I believe it's feasible and probably easier than implementing the NEC ADPCM algorithm from that thesis.

The algorithm will be helpful but trying to convert the assembly code will be too difficult (for me) or we will be waiting forever to have something that works. I have finished my WAV file script and I can use it generate square waves of different frequencies, so I have some sounds to test with the encoders. One of the encoders was written for an old PC Engine project and actually has some commented code(!) so I will start with that.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
[quote=Vag]I have finished my WAV file script and I can use it generate square waves of different frequencies, so I have some sounds to test with the encoders. One of the encoders was written for an old PC Engine project and actually has some commented code(!) so I will start with that.
Great! The fact that you'll use code that was written for the PC Engine is so funny and I have to tell you I love PC Engine! I have translated 5 games for this console, including my first ever translation (Wonderboy in Monsterland). It has such good games...

Btw, if you want, I can alter the original Golden Axe so that it plays the welcome sound when the FBI logo is first shown, if you want to easily test the sounds you make (you'll just have to replace the sound in mpr-12384.ic6).

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
I have been using M1 to test the sounds, but I should write a script to automatically patch the sound rom or at least import the ADPCM files and put the command bytes in the correct position so that I can copy-and-paste the bytes into the sound rom.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I finished with the code that plays a sound when the logo is fully shown (it's 80 bytes long). It only does it when the demo sounds setting is on, and when the logo shows up by itself - the logo also shows up when you insert a coin, but I didn't want it to play the sound in that case. Also, I have distinguished the case it shows up right after booting up, so the sound that time is the "welcome" voice. The other times, it's the Game Over "song" (which is 3-4 seconds long, and in M1 it's number 196).
I temporarily replaced the welcome sound with one in Greek that says the same, of course it's too low and it has noise. Even like this, it's so cool to have a sound replaced.
My next task is to find the pointers of the sounds, so I can move them around tin the ROM.

Last edited by Vag; 11/14/24 02:54 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I just found the sound pointers, they are in ROM file epr-12390.ic8, at offset 0E8C.

First, here are the offsets of the sounds, in mpr-12384.ic6:
1. 0000 - 1st bank
2. 0F70
3. 18D0
4. 2200
5. 2590
6. 2E80
7. 4000 - 2nd bank
8. 4910
9. 4D70
10. 5540
11. 6610
12. 8000 - 3rd bank
13. 8600
14. C000 - 4th bank
15. D760
16. 10000 - 5th/6th bank (there doesn't seem to be a bank change in 14000, weird)
17. 15300
18. 18000 - 7th bank
19. 1C000 - 8ο bank
20. 1DB40

Now take a look at the bytes of the pointers, in epr-12390.ic8:
00 00 70 0F D0 18 00 22 90 25 80 2E 00 00 10 09 70 0D 40 15 10 26 00 00 00 00 00 06 00 00 00 13 60 17 00 00 00 00 40 1B

I separated them per bank (but that's not absolutely correct, you'll see why, below):
0000 700F D018 0022 9025 802E - 1st bank
0000 1009 700D 4015 1026 - 2nd bank
0000 0000 0006 - 3rd bank
0000 0013 6017 - 4th bank
0000 - 7th bank
0000 401B - 8th bank

Now, the following bytes seem to be telling us the bank of each sound, I'll call it a "bank table"! Here they are:
00 00 00 00 00 00 01 01 01 01 01 02 03 02 04 05 03 06 07 07
They are 20 bytes, as the sounds are 20. The sounds are not in a perfect increasing bank number order.

Here's a count per bank number:
00: 6
01: 5
02: 2
03: 2
04: 1
05: 1
06: 1
07: 2

:-)))

Now we can move the sounds around in the ROM, to utilize the empty space even better. I won't do that right now, as there is no point unless I can add new sounds first.
If we want to add a sound, we'll need to somehow insert 2 bytes at the end of the pointer table, for one extra pointer, and one more byte after the bank table! You can't just add bytes and expect it to work...
There's still hope though, as after the bank table, there are 40 more 00 bytes. If we're lucky, they are fillers/empty space, so I could use some of them to add new sounds.
There must be a byte that defines the number of sounds, or bytes that have the offset and length of the pointer table and the bank table.

1 member likes this: Dodg
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
I temporarily replaced the welcome sound with one in Greek that says the same, of course it's too low and it has noise. Even like this, it's so cool to have a sound replaced.

What software and settings did you use to generate the new sound? I have not managed to get any sounds to play correctly yet, except for one that played at the wrong sample rate.

I have been running some tests to generate ADPCM files. When you look at the waveforms you can see that something interesting is happening:

[Linked Image from i.ibb.co]
[Linked Image from i.ibb.co]

Each of those sets of waveforms is 128 bytes long and uses the same repeating character (for example, the very first waveform is 0x7F x 128 bytes, then 0x70 is used, then 0x6F, then 0x60, etc.) and there are patterns there that can be identified with some more testing.

EDIT: good job on finding the pointers!

Last edited by Dodg; 11/14/24 06:04 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
What software and settings did you use to generate the new sound? I have not managed to get any sounds to play correctly yet, except for one that played at the wrong sample rate.
Audacity, I saved as VOX ADPCM, but I can do something similar if I use sox to save as another ADPCM variant. I just have to add the repeating 53 bytes (and the last 93 byte) manually. It sounds very low in the game, and it seems to affect the volume of the next sounds. If you play them some times, you can hear their volume increases. But that's temporary, I'm really hoping you can find a way to produce clearer sounds :-)

Originally Posted by Dodg
EDIT: good job on finding the pointers!
Thanks!
I can't wait to find how to add sounds!

Many Sega System 16B games are games I'd really like to translate. I had an attempt at Passing shot, 20 years ago, but it's lost, so I will do it again, eventually. Wonderboy 3 is on my list as well. But the game I have decided to translate after Golden Axe, is Shinobi :-)
So, I'm hoping we find a way, because I'd like to do it with more games :-)

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
At last, I can now add new sounds!
First of all, there is a byte that holds the number of the sounds, only it adds 1. So, 20 sounds are 14 in hex, this byte has 15. If we want to add one more sound, we must change it to 16. Its address is 0E60.
Second, we have to make room, so we can add bytes. The pointer table and the bank table have pointers themselves. As it usually happens with pointers, they are some bytes before. We don't need to move the pointer table, only the bank table. If that goes somewhere else in the ROM (there's a lot of empty space at the end of the ROM), the pointer table will have 20 empty bytes right after it; that's room for 10 new sounds. Even if we wanted to add more, we could move that table as well. The pointers are two bytes and they have the address. The bank table originally is at offset 0EB4, so the pointer must be B40E. It's at address 0E73. We can move the table to address 7D00 for example, and also update the pointer to 007D.
The id of the new sound will be 55 in hex.

Here's a part of goldnaxe.lst, somewhere in M1's path:
#084 [Voice]
#083 [Voice] Dead
#082 [Voice] Yell
#081 [Voice] Woman
#080 [Voice] Woman Yell
#079 [Voice] Dragon strike
#078 [Voice] Village People Fleeing
#077 [Voice] Thunder
#076 [Voice]
#075 [Voice]
#074 [Voice]
#073 [Voice]
#072 [Voice]
#071 [Voice]
#070 [Voice]
#069 [Voice]
#068 [Voice] Magic dwarf
#067 [Voice] Magic dwarf
#066 [Voice] Magic dwarf
#065 [Voice] Welcome

I had written this:
Originally Posted by Vag
there are five things I would like to do:
1. Convert sounds to NEC ADPCM, so I can replace the "welcome" sound.
2. Find the sound pointers and be able to move them around in the ROM, to take advantage of the available space.
3. Add new sounds.
4. Play the sounds in the game.
5. Adjust the service menu so it shows the new sounds.

Obviously that's optimal, I'll be more than happy with replacing a sound :-)
Well, 2, 3 and 4 are not a problem anymore :-)
I will play around with the service menu tomorrow, I'm expecting this to be a little easier.

As for M1, how does it find the sounds? Does it recognize them dynamically, from the ROM? Would it just see the new sounds (assuming there are no problems/errors with the bytes), or do you manually input the values? E.g. "#078 [Voice] Village People Fleeing" looks typed. Of course I will try it tomorrow with new ROM files, to see if it likes it.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
As for M1, how does it find the sounds? Does it recognize them dynamically, from the ROM? Would it just see the new sounds (assuming there are no problems/errors with the bytes), or do you manually input the values? E.g. "#078 [Voice] Village People Fleeing" looks typed. Of course I will try it tomorrow with new ROM files, to see if it likes it.

M1 emulates the Z80 sound chip and puts a value in the sound latch memory location (0xE800) to play the sounds. In M1, the track list for Golden Axe is manually written and you can change it if you want. If this list is deleted or does not exist, when M1 starts it will put 0x01 in the sound latch and (maybe) play a sound if 0x01 is valid. When you select the next song, it will put 0x02 in the sound latch and try to play a sound. You can continue up to 0xFF. The starting number and end number are defined in m1.xml but the number cannot be greater than 255 because it has to fit in an 8-bit memory address. M1 does not know if the sound values are valid, so you just have to try all possible songs until you find one that works. Also, M1 does not know what type of sound it is supposed to play, it is the Z80 that controls everything.

I do not know how the Z80 chip knows whether to play music, a sound effect, or an ADPCM sample just using the sound latch value. To find out you would need to disassemble the Z80 code and look for any code that reads 0xE800. Then, I would assume it will jump to different places in memory using this value. The rom you mentioned before (epr-12390.ic8) contains the Z80 code, so it has access to the bank information.

I was able to add a (noisy) new sound to the ROM using SoX - I used the SEGA logo sound from Sonic the Hedgehog smile Audacity still does not work for me - I always get an error message when I try to export to VOX. Hopefully there will be some progress soon - I found some more code examples with comments for other ADPCM codecs that I can look at.

Last edited by Dodg; 11/15/24 01:24 AM.
Joined: Mar 2001
Posts: 17,258
Likes: 267
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,258
Likes: 267
The usual way a sound driver like that works is that the codes from the latch select sequences from a table. Sound effects or voices are a sequence with just one or two notes. That way the code is very straightforward, and you have maximum flexibility for something like the "Sonic spills his rings" sound where there's a short burst of a bunch of notes, but it's still technically a sound effect.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Thank you, I will check that.

I noticed in the Z80 code that the 0xE800 memory location isn't referenced directly anywhere in the instructions - there is no "LD A,(E800)" like I was expecting. I found one byte at 0xF814 that appears to be a volume value(?) and the values in this byte also appear in the sound latch sometimes so I think the sound latch is also being used for volume control.

Joined: Mar 2001
Posts: 17,258
Likes: 267
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,258
Likes: 267
Set a watchpoint on e800 on the Z80 for reads and then cause the game to trigger it.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
I did try that but nothing happens. For example, if I do this

wp 0xF814:soundcpu,1,r,1,{ printf "0x%x set with data 0x%x\n",wpaddr,wpdata ; g }

then I get the expected result, such as

Quote
0xF814 set with data 0x3A

but when I do this

wp 0xE800:soundcpu,1,r,1,{ printf "0x%x set with data 0x%x\n",wpaddr,wpdata ; g }]

nothing gets triggered even though I can see the value changing in the memory window?

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hi, I have a small update: I found out how the service menu plays the selected sounds and I finished that part.
The sound ids are 41 to 54. When you push the button to play a sound, the value is already written in D1, but it doesn't use that. Instead, it looks it up in a table. Here are the bytes of the table:
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 00 4E 71 4E 71
It's obvious, isn't it? There is room for 5 new sounds. If there's a need to add more than 5 sounds, I could change the code so it doesn't use the table, but the D1 value.

This means I can now do any changes I want to the sounds, and the only thing that has to be done is the most important, to be able to create NEC ADPCM sounds :-0

By the way, I inserted one of the sounds I found online from that "Mk VII Warning Computer" device (from here: https://rutube.ru/video/87049aff131218a5d9bc3122fd866cc9/), just to check.
The sound quality is incredible! It's almost like hearing a 44100 Hz 16-bit sound!

Last edited by Vag; 11/16/24 02:23 AM.
Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Do you think it would be a good idea to create a GitHub repository to document this information? I think it would be a good reference tool for other System 16 rom hacks. If we include such things as a disassembly of the 68000 and Z80 code, we can add information to it as we understand more about the code. I have been using Ghidra to disassemble some other roms and the output is quite helpful because it creates hyperlinks whenever there is a jump or call to different areas of memory, and it has some other features such as being able to assign names to memory locations. It also does decompilation to C code, which is useful for understanding what the machine code does even if the compilation is not 100% correct.

Anyway, it is just a suggestion. The reason I thought about this is that I need to start documenting the APDCM encoding process using a flowchart or something similar so that I can understand the process better.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
For years, I was just releasing the translation, with the exception of Kick off 2 for the Amiga (I wrote two tutorials). Any notes were on paper and if I was happy with the result, I wouldn't keep them, the goal was the translation. Some years ago, I kept the notes for Micromachines for the SNES as it was really complicated, but unfortunately I lost them. That time, I managed to change a sprite from small to large (SNES has two types of sprites), which was something I couldn't find anywhere else, it was something I did myself. With the arcade Mighty Bomb Jack, I managed to add code in the graphics chip. These things are worth documenting, for other translators to use in that game, or for a romhacking trick in general. I'll probably write a tutorial for this one.
This time, with Golden Axe, I decided to keep notes in a file instead of paper (even though they are in Greek). Romhacking.net used to be the best place to find documents and notes, but it has stopped updating. I will definitely release my notes and maybe write a tutorial for changing the sound, but I don't know about a repository, we'll see.
The GreekRoms webpage is awful and we have to create a new one sometime, maybe I should make one soon and organize everything better there.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Testing an OKI codec today, I noticed something interesting:

[Linked Image from i.ibb.co]

The parts of the sample that look "normal" play ok in M1. The noise in the middle appears to be where the sample hits the upper or lower end of the audio values and then is clamped in the wrong direction. The noise at the start is possibly due to the wrong prediction values being calculated or the ADPCM default "state" not being correct. It seems that the first few samples are random to some extent because the encoder does not have enough samples to work with.

I adjusted the state table values from the OKI defaults to the 7759 default and the sample plays back at the normal volume (but with noise in some parts of the sample).

Last edited by Dodg; 11/18/24 07:03 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Originally Posted by Dodg
I adjusted the state table values from the OKI defaults to the 7759 default and the sample plays back at the normal volume (but with noise in some parts of the sample).
This is a big step!
I think some parts of the code should also change. Or maybe another ADPCM variant would sound better with the 7759 defaults. You would have to do something similar with different ADPCM variants (if you find the code first), but the result could be the same, who knows...

I searched the Internet some more. I was expecting to find different and rare ADPCM variants in Aminet (https://aminet.net/search?query=adpcm); I did, but I didn't even setup an Amiga to check, as they are different.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hi everyone,
I've been searching and trying stuff for days, but without any good results...
Just some various information:

At some point I really thought that it's G.721 ADPCM, but Cool Edit Pro supports it and it seems it's not.

Here are some different ADPCM flavors that can be heard in the game though (but with a lot of noise):
Dialogic ADPCM
DVI-IMA ADPCM 4
IMA ADPCM
Yamaha ADPCM

This is interesting: https://ethw.org/Oral-History:Takao_Nishitani

I have also found this ("Real Time Implementation of 32Kbps ADPCM CODEC on NEC uPD7720D DSP") here:
https://www.dbpia.co.kr/journal/articleDetail?nodeId=NODE01328118
and here:
https://koreascience.kr/article/CFKO198403977717771.page
It's in Korean, but it explains some things regarding the algorithm. It doesn't have any source code though, only 4 pages are shown and it's all text. In the first link, only the first page is readable (if you try to buy it, you buy these 4 pages). The second link has all 4 pages shown clearly; I wish I could find the original.

But I just got a reply email from a Greek girl that has a similar problem, who pointed me to this page: https://wiki.muc.ccc.de/millennium:voiceware
that also has a link to this decoder: https://github.com/muccc/millennium/tree/master/code/voiceware-decoder
I just started reading it, it says there are opcodes (e.g. for echo, looping, fade out) and also that you can have PCM sounds instead of ADPCM sounds.
Well, if we're not able to produce new ADPCM sounds, but we can use PCM sounds, I will do that ;-)

I need some time to experiment with the opcodes and the PCM, there's still hope :-)

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
In Alien Syndrome, the repeating opcode byte that means 128 bytes of sound data will follow, is 59, not 53 like in Golden Axe. According to the information in that wiki, this also means the frequency is 6000 Hz. So imagine if you could clear/enhance the original sounds with an AI tool and then convert them to NEC ADPCM 8000Hz. You can have the same sounds, just with better quality. I must say that there is a lot of empty space in the sound ROMs, enough for many sounds, if not all of them, to be converted to 8000 Hz ;-)

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I have found some more things...

The Sega AI computer uses the uPD7759 and has a ROM with NEC ADPCM sounds. Here is an interesting thread about the Sega AI Computer and the dumps (page 2) :-))
https://www.smspower.org/forums/15244-SegaAIComputerReverseEngineeringThread

Here's a pdf with a few new details: https://portal.etsi.org/stq/workshop2007presentations/Wideband%20Speech%20Telephony%201984-200.pdf
It calls it "WB-ADPCM" for (wideband) and it has a diagram. It also says "a combination of the French and the Japanese Codec candidates was standardized: G.722 (1988)".

I found this page https://milkchoco.info/archives/9324 that refers to this thread. It says "At the moment, I'm struggling to make software that can output NEC ADPCM."!

As I was searching for the uPD7720, I found this very interesting page: https://pawozniak.com/
"The aim of this project was to develop a fully functional emulator of the Speech Plus CallText 5010 hardware voice synthesiser used by Professor Stephen Hawking".
That device included a uPD7720 chip. They made a uPD7720 emulator, based on higan, which emulates the uPD7725.
I contacted Mr. Pawel Wozniak and Mr. Peter Benie, who were both helpful and extremely polite.

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
It seems that the μPD7730 or μPD77C30 might be the only chip that functions as a dedicated ADPCM encoder - the other chips are either decoders or general purpose DSPs. I can only find a 2 page datasheet about this chip although I have not looked in the product catalogs yet.

I also found a diagram on page 5 of this 7751 datasheet that shows how the audio samples are mapped to ADPCM codes.

Last edited by Dodg; 12/01/24 03:16 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I found this question, 2 days ago: https://retrocomputing.stackexchange.com/questions/30984/what-adpcm-algorithm-did-nec-use-in-their-%CE%BCpd775x-chips
I hope someone will manage to write an encoder. The information there helps a lot!


As for the responses from Mr. Pawel Wozniak and Mr. Peter Benie, I will show everyone Peter Benie's message:

"Hi,
In our reverse engineering project, the original authors had simply discarded any code written by the people who built the CallText interface, and replaced it with their own byte-code interpreter for KlattTalk and supplied their own routines to generate the wave forms.
There was some digital processing done on the 7720, but I doubt it was any standard encoding, because there was no need to match any standard. The 7720 doesn’t have any sound-encoder, so it has no special support for ADPCM.
The two things the 7720 has that make it special are:
The 16 x 16-bit multiplier – one multiplication per clock cycle, and
On each cycle, the operation code tells all the functional blocks what to do, not just one block.
This is how it gets high throughput, and is what makes it a DSP chip rather than a general purpose CPU.
That doesn’t help you though.

Something that stands out from the datasheet is that ADPCM is not a single standard – it is a description of a technique for encoding. It is a bit like saying a number is encoded as Floating Point; it may be true but that leaves open several arbitrary choices for the encoding of mantissa and exponent.
I couldn’t find a manual with details for the 7759, but looking at
https://github.com/mamedev/mame/blob/master/src/devices/sound/upd7759.cpp#L494
your repeated byte does indeed mean 128 bytes come next, though the comments in the code more correctly say 256 nibbles. These are fed, one nibble at a time, into the ADPCM state machine in lines 327-365.
You have to stare at the state machine for a while to figure out what it does, but when you see it, it turns out to be quite simple. It matches the block diagram on page 5 in this paper:
https://people.cs.ksu.edu/~tim/vox/dialogic_adpcm.pdf
with the exception that on the 7759, the step size and output size are 9 bits, not 12, so scale everything down accordingly.

The key thing to note is that the values in the input data represent the differences between successive output values.
In order to get both fidelity and range, these differences are scaled according to one of the curves in this diagram.

[Linked Image from i.ibb.co]

To calculate the next output value, the decoder looks up the input value on the selected curve and adds that amount to the previous output value.
It then picks a new curve, depending on that input value. For small input values, it picks a shallower curve to use next time. For large input values, it chooses a steeper curve.
That’s all ADPCM is.

In more detail:
Let curves[0..15] be the selection of curves in the above diagram, each mapping [-7..-0, +0..+7] to [-255 .. +255]
Let selected_curve = 0
Let output_value = 0
For each input value: # input is in the range [-7..-0, +0..+7]
# Step 1 – calculate the next output value.
output += curves[selected_curve][input_value]
# Step 2 – pick the next curve
If |value| in {0, 1}: selected_curve -= 1 # pick a shallower curve
If |value| in {2, 3}: do nothing
If |value| == 4: selected_curve += 1 # pick a steeper curve
If |value| in {5, 6}: selected_curve += 2
If |value| == 7: selected_curve += 3 # pick a much steeper curve
Clamp selected_curve between 0 and 15 inclusive.

The input values are encoded as sign-and-magnitude, so -0 and +0 are distinct values, both with magnitude 0. The steeper curves treat -0 and +0 differently.

An interesting feature is that both the Dialogic algorithm and the 7759 algorithm both use 4-bit sign-and-magnitude data for the input stream, which begs the question, what would happen if you were to put the data intended for one algorithm into the other?
In general, positive values would yield a rising slope, and negative values would yield a falling slope. Furthermore, large values would result in a steep slope and small values would result in a shallow slope. But if the slopes were chosen differently, the shape would be wrong and sound would be distorted.
There’s a very high chance that the fundamental mode would be clearly audible and at the correct pitch (modulo sample rate); you’d recognise which sound it was, even though it would sound ‘off’.
You might also run the risk of overflow if the output values were larger than intended. In the mame emulator, output value overflow results in undefined behaviour (only unsigned integers have defined overflow behaviour), but in practice it is likely to result in wraparound, which you would hear as a very loud pop.
You would almost certainly get a d.c. offset in the output, but you normally wouldn’t be able to hear that except on the transition to a silent block. This offset would look like a random walk – varying but spending most of the time going nowhere. But if you waited long enough, it would eventually be large enough to make normal data cause an overflow, which you would definitely hear.
Based your description and on the above, I’m convinced that what is going on in the noisy sounds is that you are feeding in data intended for a different set of curves.
In the ksu paper, page 4 shows a block diagram of the simplest possible encoder, which will let you make new sounds.
The encoder can’t produce a perfect output – it will have some quantisation error. The important thing to note from the diagram is that the differences, d(n), are not the differences between successive input values; they are the differences between the current input and the immediately previous quantised output. This has the effect of carrying any error forward to the next calculation; the error is never lost, but it might take several cycles for it to be incorporated, depending on which curve is selected.

I don’t know if you’ve come across the z-transform notation before. In the block diagrams, most of the boxes are assumed to take zero time and have no state. The z^-1 boxes, are a one position shift register so they do have state; on each operation, a new value goes in and the old value is pushed out. This means that when you turn on the “machine”, there must already be a value in the shift registers. For both of them, use the value 0 to match the implementation of the 7759 decoder.
I hope that’s of some help.
Peter"

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
...with the exception that on the 7759, the step size and output size are 9 bits, not 12, so scale everything down accordingly.

As I understand it, this would mean that the estimated (or predicted) value must be clamped to a two's complement 9-bit value (+255 to -256 or +255 to -255) and the values in the step table also cannot be greater than these values. So, does that mean that the original sample value must be converted to 9-bits as well before the difference is calculated?

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
To tell you the truth, that confused me. What I know is that the encoder needed 12-bit PCM as source, to convert it to 4-bit ADPCM. The decoder would then convert that to 9-bit PCM, that's how I understand it. If that's the case, we must ignore the 9-bit part.
As for the noise, maybe the source sound must be converted to 12-bit first, and then converted to ADPCM with the Dialogic algorithm. Maybe it's simple I mean, except that initial conversion. After all, if you import the ADPCM file to Audacity as raw VOX, the sound is clear - and VOX is really Dialogic ADPCM.
Unfortunately I have no time these days, I can't wait to try some more things, hopefully next week.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hi everyone,
I haven't really done anything about the sounds for at least a week, but yesterday I decided to finish everything else.
I fixed all issues and finished all remaining details. The last remaining thing was the memory test. I found the checksum that is used in the memory test in the service menu and I updated it with the new one; the memory test was finally a pass. But then I saw that the game does has protection after all. The sounds ids are all reduced by one, so you hear wrong sounds, and the players controls are swapped! Probably there are more surprises. So if you alter the ROMs, you either see the memory test fail, or you have a damaged game.
Well, I am hoping I can bypass this, by using balancing bytes. I'll try writing values to unused zero bytes that would change the new checksum, so that it remains the same as the original.

Anyway, that doesn't have to do with the sounds... I can't stop thinking that the sound is clear when you import it as VOX (which is Dialogic ADPCM). I believe the key is that the encoder uses 12-bit PCM sounds and not 16-bit ones, like all the sounds I had been trying to convert. ChatGPT suggested that instead of converting a sound to 12-bit PCM, I could normalize it (at least for testing), so that the PCM values are not over the maximum values of a 12-bit sound (4096). So yesterday I used Audacity to normalize a sound, in fact I reduced the volume by 24 dB (ChatGPT suggested 24 dB). Obviously the sound in the game is low, but it had significantly less hiss and noise! Maybe -24 dB wasn't enough and there were still values over 4096, and that's why there is still some noise. Most probably, this is the reason for the noise and the encoder must use 12-bit PCM sounds.
I'll search for existing tools that you can use to convert to 12-bit, for now :-)

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
I'll search for existing tools that you can use to convert to 12-bit, for now :-)

In the example codecs I have looked at, one of the OKI encoders converts 16-bit samples to 12-bit like this:

Code
if (sample < 0x7ff8) {
    sample += 8; // round up the sample value
}

sample >>= 4; // convert to 12-bit 

Processing the original samples with low pass or high pass filters will help, but the cause of the problem seems to be with the PCM values not being converted to the correct step table values. I saw in the datasheet that the 7730 can accept 16-bit samples via a separate ADC chip so converting to 12-bit may solve some problems but there may still be the "wraparound" effect that Peter Benie mentioned. I noticed that if I really bitcrushed the predicted values to a stupid value (7-bit?) then it actually played back in M1 without any noise, although the sample sounded very flat (bandwidth limited, like being played down a telephone line).

I am still looking into this, but I got distracted trying to fix some PowerPC code smirk I am having difficulty understanding how to determine what the correct step table values are apart from guessing what the values might be and how many values there are. This has always puzzled me - why does OKI use 49 values, but IMA use 89? These values all generate a curve of some type, so it might be possible to work out an equation to draw a new curve and then try different combinations of values that will fit the curve. I think you should release the translation as soon as you have fixed the remaining issues because the work you have done is very good, and go back to replace the samples later. I understand that it is important to have everything finished when you release the ROM but the game is complete without it and if you have limited time to work on ROM hacks it would be better to spend your time on the next System 16 game. By that time, maybe we will have been able to make some progress.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hello everyone,
I still haven't done anything about the sound encoding... Instead, I managed to change the service menu and the settings submenu. I added three settings, that are saved in NVRAM, so they are permanent. You can move the lever up/down to select a setting, or left/right to change the value of a setting. The three settings are the starting stage, the violence level and the music. The starting stage is operational; you select a stage and then you start a new game at that stage :-) The other two settings are not operational yet, I'm hoping this will change soon. In the Japanese version, you see blood dripping from the SELECT PLAYER letters, and also Ax Battler decapitating an enemy. In the setting, you can select none, one of them, or both. I haven't worked out how the game determines it's the Japanese or the English version yet. The last setting is for music during attract mode; there will be no music, all songs, random song, or a selected song. There is already a DIP switch setting for attract mode sounds, this will work independently.

I started looking at the music and I'm able to play the selected song. But I just realized that when I start another sound (like the sound I want in the logo), the music stops. On the other hand, the other sound effects in the attract mode don't affect the song. The way I play a sound, is to write its id (the number M1 also uses) at address FFECFC (FF6CFC or FF2CFC have the same effect). If I do that with a song, the song will play simultaneously with the other attract mode sounds. The problem is that I can't play another sound that way, because it will stop the song. It's like they are on the same channel, and there can only be one. Does anyone know how I should play the sound independently?
I will also try to determine when the sound stops (so I can repeat the song, or go to the next one).

Joined: Mar 2013
Posts: 82
D
Member
Member
D Offline
Joined: Mar 2013
Posts: 82
Originally Posted by Vag
In the Japanese version, you see blood dripping from the SELECT PLAYER letters, and also Ax Battler decapitating an enemy. In the setting, you can select none, one of them, or both. I haven't worked out how the game determines it's the Japanese or the English version yet.

There is a separate ROM set (set 4) for the Japanese version, so perhaps the animations do not exist in the world version?

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
The graphics exist in all ROM versions. Also, most of the text also exists twice (probably the second instance is for the Japanese version) - which is like a present in romhacking, plenty of unused space for all these modifications ;-)
According to my experience with other games, the code should be there, as well. E.g. in Liquid Kids, the only difference between the three versions is a single byte (the last one, if I'm not wrong), which works as a flag. I've seen it in others, as well. So, I'm hoping I can find out which condition enables the code that shows the blood and the decapitation and use a different condition. Of course, there is a possibility the code is not there, and the graphics are just useless remains. Even in that case, it would be theoretically possible to find that code in the Japanese version and copy it.

I'm planning to work with the songs tonight. I decided to start the songs by writing to address FFECFC, because that works perfectly and he songs can be heard together with the other sounds. I will just have to find out what changes when the song finishes, so I can repeat it or go to the next song or a random song, and generally perfect the code for this. This means that after that, I will have to change the way the sound that was to be heard when the logo is shown is played. I will have to find out exactly how the game does it with the other sound effects.

By the way, I used the bytes that change when the buttons are pressed or the lever is moved, I had to check certain bits. That was for moving the > in the settings submenu and changing the settings' values. After the code was finished, I found out that there are other bytes that are dedicated to each button press, probably to make the condition checking in the game easier. These are not mentioned in the System 16 specs, so probably they have to do with the program. I'm mentioning it, because I suspect the game does the same with the sounds, or maybe even the version flag. So, writing to address FFECFC starts a sound or a song, but also there's another byte for this.

Well, one thing at a time. First, I'll make it play the selected song (or a random song, or all of them), detect when it's finished playing and repeat it. Luckily, I don't have to deal with stopping the song, it stops when you go to the select player screen, or to the service menu :-)
Then, I will have to deal with the other sounds, and after that, with the blood and the decapitation.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I have a small update, the setting for music in attract mode now works as intended :-)
You can select any song you want, or all songs, or a random song (really random).
Some songs just end, some others loop automatically. So, if you select a certain song, there are two cases. If it ends after a while, the program has to repeat it. So I put a kind of a timer, which is the loop iterations. If it's a song that loops, the timer doesn't update, so it keeps playing. If you select to listen to all songs or random songs, then they all need to stop when the timer is zero.
This needs fine-tuning only, I have to determine the best timer values for each song. Also, there are times the code doesn't go in the loop, so the timer halts, I will have to fix this for precision. Finally, I have to reset the timer at certain times, like when you are starting a new game, when you go to service menu, at boot; this is easy.
In the meantime, I just found a real timer the game has, to keep time statistics :-o If I can't achieve good precision with mine, I will change the code, to use the internal timer.
Btw, if you use the DIP switch for attract mode sounds, it mutes the songs too, unfortunately. So, you can have no sound, sound effects only, or sound effects and music - you can't have music only.
I'm pretty sure there isn't a byte in the main memory to detect if a sound has finished playing, I found one in the Z80 memory only, but it wouldn't help with the songs that loop anyway.

Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
I couldn't sleep at night, thinking that the timer wasn't 100% accurate... So I changed the logic, it is updated independently, when the system timer is updated. The routine for the music just checks it now, it doesn't set it. I also have the routine run in any case, because there were times it wouldn't run (like during the screen being revealed, or when the logo is shown). Finding the right times for each song was really time consuming, I spent a whole night listening to the songs repeatedly (I survived). Now there's 100% accuracy in music during attract mode :-)
Also, I managed to exclude the first time the logo is shown. This means it can play a sound when it's shown, without messing with the songs. The music starts afterwards, when the title screen is shown. The other times the logo is shown (by itself), music is playing and I have no other sound. I did that because I'm not sure if I will find a way to have both a sound effect and a song, without one stopping the other. So, even if I won't find it, I can have a "GreekRoms" sound (if I can also find a way to encode NEC ADPCM sounds).
By the way, one of the songs loops, but after the song intro (all the others that loop, go to the beginning). It was hard to find the proper time for the timer for this one, but now everything works perfectly :-)

The next thing I'll try to do, is to find the code that shows the dripping blood and the decapitation (if it's possible) and enable it, depending on the settings :-)

Last edited by Vag; 01/17/25 09:30 PM.
Joined: Oct 2024
Posts: 43
Likes: 2
V
Vag
Offline
Member
Member
V Offline
Joined: Oct 2024
Posts: 43
Likes: 2
Hello everyone,
It's been a while... I halted everything with Golden Axe for some time, and I started and finished another translation. Now it's time to resume, so I'd like to give you an update :-)

h0ffman has ported Golden Axe to Neo Geo: https://h0ffman.itch.io/golden-axe. He did an excellent job, he reverse engineered the game, to do this. The Neo Geo CD version has CD audio music, and also, the sounds that came from certain movies were recorded again, in better quality! The sounds for the Neo Geo are not the same NEC ADPCM format, by the way.
h0ffman was kind enough to share the address for the game version (World/Japanese, with or without the FBI message). I tried it and I can enable or disable the dripping blood and the decapitation. Some work has to be done with the setting in the service menu, and I will implement these two (independent) settings.
There's another setting that I will implement: the timeout for the gray skeletons that show up after inactivity. The default value is 60", it can be changed to anything. A time of 1-2" changes the game completely, the screen becomes full of skeletons!

Some days ago, I got an email from Valley Bell, whom I had contacted at some point, about the NEC ADPCM format. I will share the email:

I just was made aware that there *is* a converter tool for uPD7759 samples.
As it turns out, there is a copy of the Sega Pico development tools available on Sega Retro:
https://segaretro.org/SMPS#Source_code_2
Inside, there is an archive PICOPCM.ZIP, which contains a converter for raw 16-bit PCM to "Pico PCM", which is the uPD sample format.
(Note that the Sega Pico PCM chip seems to run twice as fast as a "usual" uPD7759, so the kHz values from the tool may be off by a factor of 2 compared to what you expect.)

I downloaded it. It's a 16-bit cmd program, so it doesn't run on modern Windows, as it is. This program: https://github.com/otya128/winevdm/releases allows it to be run.
I just tested it with a wav file and it didn't recognize it. I have to find the correct format, it's a matter of time. Unfortunately I have no time at all these days, I will, after two weeks!
But I wanted to share this information, as other people also wanted to do something similar.

Joined: Feb 2004
Posts: 2,625
Likes: 332
Very Senior Member
Very Senior Member
Joined: Feb 2004
Posts: 2,625
Likes: 332
Fun fact: winevdm uses MAME’s 386 CPU core.

Page 1 of 9 1 2 3 4 5 6 7 8 9

Moderated by  R. Belmont 

Link Copied to Clipboard
Who's Online Now
2 members (R. Belmont, 1 invisible), 175 guests, and 1 robot.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,355
Posts122,423
Members5,082
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Powered by UBB.threads™ PHP Forum Software 8.0.0