Efficient RAM use by a music engine

Discuss NSF files, FamiTracker, MML tools, or anything else related to NES music.

Moderator: Moderators

Post Reply
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Efficient RAM use by a music engine

Post 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?
User avatar
Dwedit
Posts: 4470
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post 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.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Drag
Posts: 1350
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Post 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?
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Re: Efficient RAM use by a music engine

Post 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.
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Post 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.
Useless, lumbering half-wits don't scare us.
User avatar
Hamtaro126
Posts: 783
Joined: Thu Jan 19, 2006 5:08 pm

Post 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!
AKA SmilyMZX/AtariHacker.
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post 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.
User avatar
TmEE
Posts: 789
Joined: Wed Feb 13, 2008 9:10 am
Location: Estonia, Rapla city (50 and 60Hz compatible :P)
Contact:

Post 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.
User avatar
Jarhmander
Formerly ~J-@D!~
Posts: 521
Joined: Sun Mar 12, 2006 12:36 am
Location: Rive nord de Montréal

Post 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'.
zzo38
Posts: 1080
Joined: Mon Feb 07, 2011 12:46 pm

Post 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.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

And even if it's not self-modifying in the strict sense, a C64 or FDS program could stash variables between subroutines.
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post 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.
zzo38
Posts: 1080
Joined: Mon Feb 07, 2011 12:46 pm

Post 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.
User avatar
Jarhmander
Formerly ~J-@D!~
Posts: 521
Joined: Sun Mar 12, 2006 12:36 am
Location: Rive nord de Montréal

Post by Jarhmander »

neilbaldwin wrote:...
Thanks for the explanations, that was approximatively what I thought.
Post Reply