Help needed with music player
Hello everybody!
I'm a retro gaming and demoscene enthusiast (I say 'retro' because I was about one year old when it happened!), with particular interest in module formats and some experience in decoding esoteric ones. It is this latter occupation which I must now pester you lot about. I've never actually owned or used an Amiga - all my past experience and programming knowledge is on RISC OS (Acorn Archimedes as-was) and ARM assembler, which was why I found it rather daunting when I took on the project of decoding a module format based on a disassembly of the original 68000 player machine code. The guilty party in this case is the Jason Page format, as used in Fire and Ice, Uridium 2, and other games. Try as I might, I couldn't find any documentation at all (when I've solved this last conundrum, I hope to write some of my own), and so I've been writing a converter based first on the unbelievably bug-ridden Archimedes conversion of Fire and Ice, and latterly on the disassembly of the original player available from AMP. It is with this that I have become confused. I posted on the AMP forums about my problem, and was recommended to come here and ask where there were likely to be more 68000 programmers reading. The problem I have is with this piece of code which is called for a particular instrument command: Code:
MOVE.L (A3)+,D0 There is another instrument command which does the same thing, but without checking if the value read is 0. These two commands combined mean that the only two values _SampleLoopLen can take are either 0, or that of _SampleLength * 2. All of which makes the code which actually programs the Paula chip rather odd: Code:
TST.L (_SampleLoopLen,A2) Hence the only possible value the sample start address can take is that of _SampleLoopAddress! I welcome any corrections to the above diatribe, and I hope somebody can point out where I've gone wrong. |
Jason did some cool work on Paradroid 90 and the subsequent games, always liked how the audio turned out.
Maybe you're the first to rip his player, but it might be that there's someone out there who has a working player source. As for helping, I'll check back when I'm less tired. Sample lengths/loop lengths are usually supplied as half the byte size, as the audio hardware works that way. Loop lengths (which is the same as sample lengths, as audio is always played looped) is always given in words, not bytes. DMA is 16-bit, so it reads a word on each access and then plays two sample-bytes, reads another word, and so on. Here's another Acorn fan btw, welcome and kudos for putting your first post in the right subforum! Hehe. |
Quote:
Are you sure this is the only location where the program writes to HSampleStartAddr? I could imagine the following: The sample's base address is written to HSampleStartAddr and HSampleLength is set to the full length in words from SampleLength. Then audio DMA for the channel is started. As the next step some effects will be applied (while DMA is running) and SampleLoopLen is rewritten, which also makes SampleLength smaller than its initial value (because the loop takes place with a range at the end of the sample). Now the audio registers HSampleStartAddr and HSampleLength are written again with the new values, defining the loop. Paula works that way that it will reload the HSampleStartAddr and HSampleLength into an internal latch whenever the DMA finishes (end of sample is reached). The sample is automatically restarted playing the loop range. |
Oh bother. :(
That's more or less what I was expecting it to be doing as well, but I can't tell how it's happening! Before I provide more complicated examples, here's a brief grounding on how Jason Page instrument definitions work: A sample number is specified with the note as normal, except it points not to an instrument, but to a list of instructions which give all the details of the address of the instrument, its loops, vibrato, fades, etc. Data is read from this block every 50 Hz clock tick, stopping whenever a special instruction code of $12 is encountered, at which point it updates the current volume and pitch, and fills the hardware buffer. Here's an example from the sixth world of Fire and Ice: Code:
2 0 <- _SampleLoopAddress set to beginning of sample #0 Command $10 executes a single instruction: Code:
ST (_KeyON,A2) One pattern I have noticed is that command $10 is always preceded by a command $12, which means that by the time _KeyON has been ST'd, the hardware buffers have already been updated once. I have a feeling this is important. Now, from the data above, you would assume that this produced a looping sample, $22C8 bytes long, with the repeat start at offset $8C8 and a length of &1A00. But, judging from what I understand of the code below, which is very little, what actually happens is that the entire $22C8 bytes gets played through once, and then it loops on the first $1A00. That can't be right, surely? Here's the complete unabridged hardware updating function: Code:
lbC0009FC A synth chord from Uridium 2: Code:
2 4 ; _SampleLoopAddress = sample #4 This next one is especially interesting. Judging by experimentation, I believe the correct translation of the parameters is a repeat start of $600, and length of $420. The sample itself is $1BC8 bytes long, and is a sort of high 'plink' sound used in the middle of the Uridium 2 title music. Code:
2 8 ; _SampleLoopAddress = sample #8 tl;dr version: What does ST (_KeyON,A2) mean? The hardware buffers aren't mentioned anywhere except in the one place described here. _HSampleStartAddr never changes except when specified by command $8, therefore a loop is only possible at the start of the sample, not the end. I don't think this is correct, so what am I doing wrong? I bet _KeyON has something to do with it. |
All times are GMT +2. The time now is 22:12. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.