Page 1 of 1
Efficient RAM use by a music engine
Posted: Tue Jun 28, 2011 4:44 pm
by tepples
The music engine used for Concentration Room, and Thwaite uses about 66 bytes of state, yet the replay engines in .sid files allocate only about 20 bytes
according to hyarion. Here's how my music engine currently allocates its memory:
psg_sfx_state: 32 bytes of zero page (26 used)
Channel last frequency: 1 byte per channel
Sound effect/percussion data pointer: 2 bytes per channel
Sound effect/percussion data length: 1 byte per channel
Music phrase data pointer: 2 bytes per channel
Order table data pointer: 2 bytes
soundBSS: 64 bytes of main memory (40 used)
Sound effect/percussion data rate: 2 bytes per channel
Instrument number: 1 byte per channel
Envelope current volume: 1 byte per channel
Current note pitch: 1 byte per channel
Current note remaining duration: 1 byte per channel
Current phrase number: 1 byte per channel
Phrase transposition: 1 byte per channel
Tempo: 4 bytes
Order table loop position ("segno"): 2 bytes
Rows left in order table entry: 1 byte
Global music pause: 1 byte
Is there something I appear to be doing horribly inefficiently?
Posted: Tue Jun 28, 2011 5:18 pm
by Dwedit
Do SID chips have readable registers? Much RAM use in a NES music engine is from needing to have readable copies of the contents of the audio registers.
Posted: Tue Jun 28, 2011 11:59 pm
by Drag
DNSF2 only uses 5 bytes of ZP, but it uses 147 bytes of regular memory.
But then again, I was optimizing for CPU time, and I have features like subroutines, track volume, combined volume/duty envelopes, pitch envelopes, pitch bends, etc. This is also for 8 channels of sound, 4 channels forming one layer (for music), the other 4 for the sound effect layer.
Don't worry about SID music, a lot of times, the crazy-efficient players will be very constricting, and often times will be tracker based. It might be ram efficient, but how much memory does the song data take up?
Re: Efficient RAM use by a music engine
Posted: Wed Jun 29, 2011 12:29 am
by mic_
tepples wrote:The music engine used for LJ65, Concentration Room, and Thwaite uses about 66 bytes of state,
Did any of those games run low on RAM? To the point where a dozen-or-two extra bytes would have mattered..?
Your music engine is using about 3% of available RAM. I'd say that's just fine. Of course you could store your music data in a VGM-like format (values to write to the APU registers, mixed with delays) and get away with maybe 3 or 4 bytes of RAM per channel. But the music data would be huge.
Posted: Wed Jun 29, 2011 1:34 am
by Bregalad
If you wanted to use very low ram then you could go as low as :
1 pointer (2 bytes per channel)
1 counter (1 bytes per channel)
tempo (1 byte)
so you'd end up using a dozen of bytes, but then you would have crappy possibilities, no volume envelope, no vibrato, fixed duty cycle.
Posted: Wed Jun 29, 2011 9:28 am
by Hamtaro126
the smallest I've seen is what SMB1/VS/2j and the NES version of Spartan X (Kung Fu) uses mostly $F0-$FF (They share the same music engine).
But for me, SMBDIS allows Music RAM in these areas to easily go to places in Main RAM or Extended/Save RAM, such as $6000-$600f
Talk about portability!
Posted: Fri Jul 01, 2011 1:10 am
by neilbaldwin
Dwedit wrote:Do SID chips have readable registers? Much RAM use in a NES music engine is from needing to have readable copies of the contents of the audio registers.
Some, but they're of very little use.
What you're missing here (especially comparing to SID) is that you've much more scope for using embedded variables and self-modifying code as the C64 is RAM-based as opposed to the NES being ROM-based.
Self-modifying code is ubiquitous in SID players.
Posted: Mon Jul 04, 2011 1:21 am
by TmEE
I am making a sound system for SMS/GG right now, and I seem to be quite memory hungry, right now each channel uses 16 bytes of memory (but I do need more), and there's 4 of them. I also need some room for SFX etc.
I have set aside 256 bytes of RAM that the system can use up. With FM chip support I will probably do use up most of the 256 bytes.
Posted: Fri Jul 08, 2011 7:53 pm
by Jarhmander
neilbaldwin wrote:What you're missing here (especially comparing to SID) is that you've much more scope for using embedded variables and self-modifying code as the C64 is RAM-based as opposed to the NES being ROM-based.
Please explain what you mean by 'embedded variables'.
Posted: Fri Jul 08, 2011 8:01 pm
by zzo38
~J-@D!~ wrote:Please explain what you mean by 'embedded variables'.
Does it mean storing the value of some variables where the literal immediate values are used for some CPU instructions? If that is what it means, I can see it is self-modifying code and doesn't work in ROM-based.
Posted: Fri Jul 08, 2011 8:38 pm
by tepples
And even if it's not self-modifying in the strict sense, a C64 or FDS program could stash variables between subroutines.
Posted: Mon Jul 11, 2011 2:24 am
by neilbaldwin
~J-@D!~ wrote:neilbaldwin wrote:What you're missing here (especially comparing to SID) is that you've much more scope for using embedded variables and self-modifying code as the C64 is RAM-based as opposed to the NES being ROM-based.
Please explain what you mean by 'embedded variables'.
Probably an inaccurate choice of phrase but what I meant was:
because the C64 is RAM-based, you don't really need to apportion a section of RAM for your variables in the same way you do on the NES. So you could have (C64):
Code: Select all
lda #$01
sta myVariable
rts
myVariable: .db $00
lda #$02
sta myVariable
rts
lda myVariable
sta someHardwareRegister
rts
So the variable 'myVariable' is somewhere in the code and not in ZP or BSS.
Or, self-modifying code:
Code: Select all
lda #$01
sta _myVariable+1
rts
lda #$02
sta _myVariable+1
rts
_myVariable:
lda #$00
sta someHardwareRegister
rts
So the two 'routines' store either #$01 or #$02 in the byte in memory after the LDA opcode (_myVariable+1). Again, no ZP or BSS is used but you're still using a RAM variable.
Posted: Tue Jul 12, 2011 2:46 pm
by zzo38
neilbaldwin wrote:Or, self-modifying code:
Code: Select all
lda #$01
sta _myVariable+1
rts
lda #$02
sta _myVariable+1
rts
_myVariable:
lda #$00
sta someHardwareRegister
rts
So, it is what I have thought. I have thought of these things before, too, but I was not thinking of it in terms of C64.
Posted: Tue Jul 12, 2011 8:26 pm
by Jarhmander
neilbaldwin wrote:...
Thanks for the explanations, that was approximatively what I thought.