More sample/timer woes

More sample/timer woes

by ferris

This week was pretty busy, so I didn't get as much coding time as usual.. but I did make some progress.. I think?

The main thing I did was reverse-engineer Galactic Pinball's sample playback code, and made a Rust sample extractor for the ROM to prove my understanding was correct. At first, it wasn't :) . I had missed a crucial detail that meant I was pumping out samples from the ROM half as fast as I was supposed to, so it took a couple tries, but I got it.

The whole point of that was to figure out what the sample playback routine was (along with the target sample rate, which is why I needed to extract the sample as well) in order to figure out how the timer is supposed to work, as my emu still doesn't play these back at the correct rate. I had renounced this as having to do with the CPU not being cycle-accurate yet, but last weekend I sat down and tried hardcoding instruction lengths to see if that would make any difference. Spoiler alert: it didn't. So that's why I was looking at the timer again.

The really frustrating bit about it though is that to play the sample back correctly, samples need to be decoded and sent to the audio hw (in this case just acting as a 1-sample buffer) at a rate of 20khz. This yields a sample period of 50us. Ok, simple enough, but here's the catch: our timer's smallest interval can only fire every 20us. Since 50 doesn't evenly divide into 20 (unless everything I know about the universe is wrong, which to be honest I haven't ruled out yet at this point), that doesn't actually make any sense.

I tried a ton of stuff to hack the timer into working how we expect for this game in particular. While this led me to something that works pretty well and doesn't appear to break any other games, I really don't think it's correct, as it basically just adds a 7.5us delay from when the timer transitions from disabled -> enabled, and then there's some details with reloading values and how many ticks will go by before the timer interrupt fires. But, this was really just an exercise to see what could work, and at least in that way it was a success.

So, currently I'm resorting to reverse engineering more sample playback routines from other games (especially a few that appear to conflict) to see what I can find. The reason I'm sticking with these is that they're pretty easy to isolate from other code, they don't tend to be very much code, and it's very obvious to notice when they're wrong, so it should be a pretty decent strategy. At this point I don't really know what to expect yet, but just need to gather more intel!

Also, I started working on demo tooling a bit! Tomorrow I hope to get shader include done, which is pretty high on my want-to-haves for the tool. Basically this allows one to have #include "some_file.glsl" preprocessor statements in shader code similar to C/C++, which should be a pretty effective way to de-dupe code. It's not super fancy, but it does touch a lot of bits of our code (asset management/file watching, export, replayer), so it's not trivial, but it's pretty fun.

Until next time!

Last Edited on Mon Feb 27 2017 16:49:37 GMT-0500 (EST)