Archive for July, 2010

4 channel sample driver

Posted in Audio on July 17, 2010 by pcedev

Dammit. I was using the test code to try something out (cool destruction/corruption type effect on DDA), when I realized I never initialized the damn VDC. But the V-INT is enabled. And the V-INT routine resets the TIMER unit. So as you can imagine, you get random results on power on.

So, I’ll have to fix that and re-upload the source code/rom. Off to do more audio tests.


I’m back

Posted in Audio on July 16, 2010 by pcedev

Home. Feels good after two grueling days at 10+ hours of 120+ heat in an non air conditioned house. Man, I think I lost 5lbs just by sweating. And I thought Tucson was hot. ;>_>

Ryphecha did a test and found something really interesting. Not sure yet, but either going from D7=1 to 0 or 0 to 1, of $804, causes the waveform pointer to walk by +1. Interesting.

I got the evening free, so I’m gonna write up some more audio tests, yay!

Oh and AamirM, re-writes go faster than you think ( at least.. I think). 😀

Wow.. three days in a row for audio tests :D

Posted in Audio on July 13, 2010 by pcedev

This time, LFO:

The run down.
_ D7: 1= Stop channel 1’s waveform pointer. 0= left pointer continue (if set to do so). This really has nothing to do with LFO. This stops the channel’s waveform and reset the waveform pointer whether or not the channels is in LFO mode. Which is handy. If the channel is on LFO mode, and writing to D7 is desired, you should write $00 to the low two bits as well. Toggling back and forth between $83 and $80 on this register gave some random inconsistent effects (gets stuck on off mode randomly), upon power on. It’s recommend to just write $80 from whatever value you had before (drop the lower bits), if you want to pause the modulation. Or just write $00 is you don’t want to reset the waveform – but do want a pause.

_ D1-0: These are the FM data multipliers. They are: $00=Off, $01=0.5x, $02=4x, $03=16x. These multiply against the signed data in the channels waveform memory, to be applied to channel 0. But there’s another effect of these values. They multiply against channel 1’s period value (or dividing the whole frequency down, however you look at it). Yes, you read that correctly. $00=N/A, $01=1x, $02=2x, $03=3x. Divide’s channel 1’s frequency by that factor. Making the modulation against channel 0 slower with each increased value, but more pronounced with each step. To see the frequency differences, hard pan channel 0 and 1 to left/right, and make channel 1’s sinewave viewable/audible ($9f@$804). And… using an FFT and the channel buffer filled with all the same value, you can see the resulting fixed step in the multiplied values against the original FM data sample.

Channel 1 will output the waveform data as normal sound in LFO mode. You can also write to channel 1’s data port and replace the waveform memory as it’s playing. Just like with other channels. It’s unclear if the new data written on the port effects the frequency modulation write away, either. This still needs to be tested. But I do know that the sound will be heard if channel 1’s volume is high enough for audible output.

FM waveform data. The data is 5bit signed when applied to channel 0’s period value. But the signed data is inverted. $00= -$10, $8= -$08, $10= $00, $1f= +$0f.

$808 is another period multiplier. It has no effect when D1-0@$809 are set to $00.

Writing to either $808 or $809 doesn’t correspond to what value is in $800.

Also curious enough, not initializing all channel registers, will randomly get you an incorrect waveform for channel 1 modulation. Even if you setup both channel 1 and 0 registers correctly. I don’t know why this is, but waveform always looks square (with uneven duty cycle).

Putting channel 1 into DDA mode and then LFO mode, causes a single value to modulate channel 0. Where this value is pulled from, isn’t known yet. But it’s not the value written to the data port when in DDA mode. No sound output or change takes place for such writes when DDA+LFO is used (unlike writing to the DATA port in buffer mode). Whatever the value was in my tests output a fixed frequency modulation to channel 0, it didn’t correspond to the multipliers 0.5x, 4x, 16x. But changing $809 lower 2 bits did have an effect (it looked closer to 1x,4x,16x applied against of a value of 6. But $06 was neither the first or the last value written to the waveform memory. But it is the value if you subtracted the first value in the sine waveform from the last. Probably just coincidence). Hmm.. maybe I should recheck the 0.5x multiplier against a few more values.

If I have time, I’ll do more audio tests tonight. But if not, I’ll be back in town for the weekend to finish up.

and Monday is a good follow up day

Posted in Audio on July 12, 2010 by pcedev

Few more things to note.

For $804:
– bits $40 set (volume bits irrelevant). Will not update waveform memory. Waveform memory pointer is reset to $00. No sound is outputted when writing to $806.
– bits $C0 set (volume bits relevant to output). Will not update waveform memory. Waveform memory pointer is reset to $00. Sound is immediately output when writing to $806. Change in volume bits causes last $806 write to be output with new volume level.
– bits $80 set (volume bits relevant to output). Writes to $806 will update current waveform memory. Waveform pointer is not incremented upon writes to $806. Writes to $806 immediately get output (no mixing). Changing volume bits causes last sample from waveform memory to be re-output (if playback speed is slow enough) with new volume level.
– Bits $1f (volume bits). Changes to volume level are buffered (single buffer). Contents of buffer are applied to new samples on the DAC at ~1747Hz. Any faster change will be ignored and the last change will show up/take effect. Left and Right channel waveforms are also out of phase from each other (about 256 cpu cycles).

SGX and PCE differences:
– $9f->$5f causes a spike on the PCE. On SGX, it doesn’t
– Volume change (any volume port). PCE: large differences cause a DC offset with a slow return to zero. Polarity direction of the spike is relative to the direction of the volume change. SGX: same, but the spike is very small in comparison.
– Waveform output. SGX is inverted in comparison to the PCE (might explain why Ootake does inverted output. Since the Coregrafx 1 (not model 2) also uses the 6280A sound chip revision like the SGX and Ki used that as a test board IIRC).

Note: Doing $df->$9f (volume bits are irrelevant) causes a max amplitude sample to be output before the channel period system starts up and updates the DAC. This isn’t a ‘spike’ like the volume DC offset issues. Whatever sample value written to DDA port prior seems to have no effect on this. And it happens on both the 6280 and 6280A.

Sunday is a great day for audio tests…

Posted in Audio on July 12, 2010 by pcedev

What a fruitful day, yesterday was. Lots to report. First, AamirM here are the zip files:
The last one has the rom. I took pics so you know what settings were used for which wave record file.

First, volume changing. Each volume mechanism sets the reference voltage and they accumulate (weather digitally or analog, I’m not sure. But it doesn’t particularly matter at this point) for the amp on the final output. The problem occurs when you have a large change in volume (up or down), the total negative voltage point drops and takes a bit to normalize back into place. For normal channels, this isn’t such a big deal. Usually, on a normal channel output – you have a sudden change of sound introduced from turning on a channel. So the sudden change of the of having a DC offset introduced into the signal and drift back, isn’t really noticeable. If it was, sound emulation would sound completely different. Instead of slightly.

The bad part about this, is when you have nothing outputting on a channel and you change the volume reg. Say for DDA. You get a spike with no accompanying audio/waveform/etc. Just a pop by itself. That’s undesirable. So, if you’re writing your own music/sound engine – don’t change the volume level of the DDA channel if you’re not outputting anything. Just leave it as is.

Second, writing to the data port while a channel is playing. This has some really interesting results. The current sample being output is replaced with the new sample. Nothing is ‘mixed’ or such. But more importantly, the channel buffer is updated! The waveform pointer is not updated though. Come to find out, a few games actually use this. All three of the Fire Pro Wrestling games do this. And so does Devil’s Crush.

They do it at a slow rate (like 60hz or less). Devil’s Crush does it even slower. The way they use it, it pseudo-randomly changes the timbre of the channel. On the first FPW game, they go overboard and it sounds terrible. But by the third game in the series, it’s more functional. What surprises me about FPW, is that they keep ‘corrupting’ the channel buffer while playing new notes. They don’t bother to reset it for each note in a track/song. Nor do they use 7khz rate with a divider/counter. You could get some really interesting sounds that way.

Third, DDA. Changing the volume on a DDA channel will cause the last sample written to be re-outputted. Changing a channel from normal->DDA->normal, will reset the channels waveform pointer. If you keep the volume active/included in that change, the channel won’t ‘turn off’ and you won’t get a spike. Alternatively, you can also write $40+vol to a channel and then $80+vol to reset it too. Both methods will reset the channel waveform pointer without turning off the channel. Though, I need to look at $40+vol and writing to the sample buffer to see what the effects might be. It’s not a normal mode to have the channel in.

Fourth, removing the spike. The change in volume has a spike in polarity corresponding to the direction of the change. By using another channel, going in the opposite direction, you can cancel out the spike (well, nearly cancel it out. It becomes very tiny). This might seem wasteful. And you’d be right. Except for one small detail. You could now in theory use the channel’s buffer as a mini DMA buffer. That means higher than 7khz output with little cpu resource. Make it high enough, and you can interleave samples of two waveforms. The high rate will cause the samples to ‘mix’ to the human ear (old Amiga trick to get 8 channels of audio). Thus, getting back the wasted channel 😉

Gate of Thunder Force

Posted in Uncategorized on July 9, 2010 by pcedev

Since I got decent server space and bandwidth, I re-uploaded the project.
If the link doesn’t work, try taking “www.” off the front of it (my old server required it, not sure if this one does).

Also, over the past year or so I’ve been wanting to create a sprite organization tutorial. Since I’ve seen a lot of PCE games with poor sprite management, I wanted to use those as examples of what not to do 🙂 I got Strider for ACD which is a huge offender, worked out as pic examples and how they could have fixed them. Need to get a few more games done like that before I can release it.


Posted in Uncategorized on July 5, 2010 by pcedev

Mairtrus release his SMB recompiled for MD, last week. Its news making its rounds on the internet.

He recompiled Doppel’s SMB source code. Doppel sent like over a year disassembling the game by hand in a debugger, commenting and figuring out what all the functions do, etc. Even gave variables label names (meaning full names) and documented what they do. And incredible job that I’ve never seen anywhere else before (the metroid disassembly floating around the ‘net is supposedly machine done with some hand tuning, but not like Doppel’s stuff). Last I heard from Doppel on IRC’s nesdev channel, he was attempting Final Fantasy 1 for NES. Not sure if that’s still active or not.

Anyway, back to Mairtrus. He used said source code and ran it through a source code translation utility (presumably his own, from what was posted at on the forums). The sound was translated as well, to use a native sound player (his own or SMSP, not sure). SMB has not mappers, so nothing to take of there. SMB also uses VROM, so no worrying about converting NES tile format on the fly (planar to packed pixel). Just a quick conversion at runtime before the main code starts. That leaves handling the tilemap, attribute, sprite table, sprite 0 fixed scroll, and scrolling on the fly (possibly gamepad, but not sure). No small feat, considering how convoluted the NES PPU is (no offense veteran nes dev’rs. Convoluted can be fun). But it’s been done before, and not just by me.

The real surprise, IMO, is the attention this has gotten. Yeah, the usually ‘can you do this’ and ‘can you do that’ requests and expectations (i.e. automatically expected it *will* happen). People are fairly impressed. People are already talking about upgrading the graphics, sound, levels, etc. This is considered huge.

Am I on the wrong platform??? I did this back in 2007 on a more complicated rom and much more real time emulation. I did this on quite a few titles with different PPU requirements: Megaman, SMB (yeah, SMB), Contra, Ducktales, Dragon Warrior, Castlevania, RoboWarrior. I guess TG16/PCE isn’t popular enough to matter. I actually anticipated this very excitement. I thought people were going to want upgrades and hacks, etc. Exactly what is happening now. I even advertised on the most famous romhacking site in the world, RHDN. I even released the source code and full project files. Hahaha. I’m totally developing on the wrong platform or something 😉