4ever2600 Posted December 31, 2003 Share Posted December 31, 2003 Quick question about the 2600 adventure game sound fx... According to the source code that was explained: ;Noise 4 : Dropping object. FA8C A5,DF LDA &DF ;Get note count. FA8E 49,03 EOR #&03 ;Reverse it as noise does up. FA90 85,17 STA &17 ;Store in frequency for channel 00. FA92 A9,05 LDA #&05 FA94 85,19 STA &19 ;Set volume on channel 00. FA96 A9,06 LDA #&06 FA98 85,15 STA &15 ;Set a noise on channel 00. FA9A 60 RTS I don't want to change the sound fx, just the pitch of it, make it a little lower toned. Is this the section that I do this? Wouldn't I just change a frequency setting? PLEASE HELP! Where's Nukey Shay!?!? Thanks in advance... - Daryl Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 Notice that the note counter itself is being used for the pitch (stored in AUDF0). There are 3 notes used for picking up/dropping (which is why performing an EOR on the lowest 2 bits is the only difference needed between them). So if you wanted to make the notes lower, I suppose that you could just insert an ASL instruction into the source code just below the NoiseDropObject_2 tag...I've noted it below...but the problem with generating lower tones is that it takes a greater difference between the notes for the change to be noticable (so if you end up with too high of values, the game will just be grumbling). One bit position shouldn't really matter all that much though. Try this: ;Noise 4 : Dropping Object. NoiseDropObject: LDA $DF ;Get Note Count EOR #$03 ;Reverse it as noise does up. NoiseDropObject_2: ASL ;ADDED INSTRUCTION-multiply acc X 2 STA AUDF0 ;Store in Frequency for Channel 00. LDA #$05 STA AUDV0 ;Set Volume on Channel 00. LDA #$06 STA AUDC0 ;Set a Noise on Channel 00. RTS ;Noise 5 : Picking up an Object. NoiseGetObject: LDA $DF ;Get Note Count. JMP NoiseDropObject_2 ;and Make Same noise as Drop. BTW this code snippet is from the optimized Adventure code...which you really ought to be using instead of the old VGR one (since everything is layed out so much better and space is freed up to insert commands like this). Quote Link to comment Share on other sites More sharing options...
4ever2600 Posted December 31, 2003 Author Share Posted December 31, 2003 I kinda see what you've done, BUT, I've been doing things a different way... I've been working on my project by looking at the explained source code and changing it on the 68kb notepad file... In other words: 0a8c |X X X X| 0a8d |XX XXXXX| 0a8e | X X X| 0a8f | XX| 0a90 |X X X| 0a91 | X XXX| 0a92 |X X X X| 0a93 | X X| 0a94 |X X X| 0a95 | XX X| 0a96 |X X X X| 0a97 | XX | 0a98 |X X X| 0a99 | X X X| 0a9a | XX | 0a9b |X X X X| 0a9c |XX XXXXX| 0a9d | X XX | The above section is the section we just looked at... My questions is, how the heck do I add a line in this mix without changing everything, AND what does ASL change into as far as 09ad |x x x x x | ? I am probably doing things the hard way this way, though I do find it easier to change, recompile (editgfx) and load in the emulator to test and play. Can you translate for me and change the above code? Lemme know... Thanks for your quick response... I'm sorry I don't totally understand the other code explanation yet... - Daryl Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 OUCH! You can't do hacks very well using just a binary editor. With those, there is no way to squeeze in extra instructions without usually messing up the rest of the program. That's where source code comes in. It lets you add things in without having to worry about addresses (since the assembler will work those out on its own). Download this file, and use it with Dasm to build a binary after you make changes to it... EDIT: this one has the easter egg signature added back in when you use ORIGINAL=1...you still end up with 81 bytes free. I also rearranged the room maps to share data more efficiently when ORIGINAL=0...leaving you with 345 extra bytes if the original signature is not used. EDIT: added the invisible surround fix posted by Channel2. adventure_optimized.zip Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 Hmmm...looking at it again, I suppose that you could use the X register in there to free up the single byte you need. Try this: ;Noise 4 : Dropping object. FA8C A5,DF LDA &DF ;Get note count. FA8E 49,03 EOR #&03 ;Reverse it as noise does up. FA90 0A ;multiply acc by 2 FA91 85,17 STA &17 ;Store in frequency for channel 00. FA93 A2,05 LDX #&05 FA95 86,19 STX &19 ;Set volume on channel 00. FA97 E8 INX ;Increase X register by 1 FA98 86,15 STX &15 ;Set a noise on channel 00. FA9A 60 RTS There you would need to edit all bytes from FA90 to FA98 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 Change these lines in ShowGFX: 0a90 | X X | 0a91 |X X X| 0a92 | X XXX| 0a93 |X X X | 0a94 | X X| 0a95 |X XX | 0a96 | XX X| 0a97 |XXX X | 0a98 |X XX | It should work...I think. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 EDIT...let's try this again... Quote Link to comment Share on other sites More sharing options...
4ever2600 Posted December 31, 2003 Author Share Posted December 31, 2003 Thanks Nukey! It worked perfect! I am going to try to mess with the optimized code, I'm sure with a little time I can figure out how to use it with Dasm... no prob. There are only 6 sound fx in adventure, Now that I've kinda changed 2 already, that only leaves about 4 to do... If I need you to convert a couple more lines of code, would you mind me bugging you? Thanks for all the help once again, although I totally don't understand it all, I will get there soon! You are the man! - Later! - D Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 It worked? j/k I think it sounds a bit flat...but it did point out another byte to save BTW binary conversion is easy if you use the calculator on your desktop in scientific mode. Just click on Hex, enter the value, and click binary. Or use a chart like this to translate the nybbles: 0=0000 1=0001 2=0010 3=0011 4=0100 5=0101 6=0110 7=0111 8=1000 9=1001 A=1010 B=1011 C=1100 D=1101 E=1110 F=1111 ...so a value of $8F for example would be 8 (1000) and F (1111). Put those together for 10001111. But you really should use the source code instead. It is much more flexible than anything you could accomplish just hacking the binary. For example, you could load the note counter into the Y register, and keep a table with a set of notes that you want to be played. When you load the A register with the frequency, you could load it as LDA $table,Y Quote Link to comment Share on other sites More sharing options...
4ever2600 Posted December 31, 2003 Author Share Posted December 31, 2003 Are you kidding? My Scientific Calc has been smoking ever since I started this project! :wink: Though I didn't know about the translation you showed me... That makes alot of sense... I can put alot more together using that... Thanks again! You'll be the first to play this baby once it's done! Thanks! - Daryl Quote Link to comment Share on other sites More sharing options...
4ever2600 Posted December 31, 2003 Author Share Posted December 31, 2003 Could you pull the same trick off on the few other sfx? You know, using the X thingy? Could you try it to the following sounds in adventure and convert it for me like you did the last one? With the a90 |xx x x | ? I shouldn't have to bug you about sound after this... I just want to bump up the pitch a couple notches... Man eaten Dragon Roar Dragon Dying Game Over Win Thanks Nukey, even if you don't have time to do this... - D Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 Nono...the X register wasn't used to change the sound....the X register was used to do the same thing that was done already...but in a shorter amount of space (i.e. set the volume and audio control). I just happened to notice that it was wasting space by loading each value seperately. It was the saved byte that allowed an additional instruction to be squeezed into the routine...and THAT instruction is what changed the sound. So changing them could be as easy as just changing the values before they are STA'ed. There are a number that have a value EOR'ed before it is saved...how about EOR'ing a different value so that different bits are flipped? Anyway, the whole thing is moot if you are using the source code...since you wouldn't be limited to do things confined to the original areas. Quote Link to comment Share on other sites More sharing options...
4ever2600 Posted December 31, 2003 Author Share Posted December 31, 2003 That makes sense... Just out of curiousity, I still could change the sfx without combining statements to save room right? By just adjusting some of the values of the code... Even if I'm not using the optimized code? Just curious... Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 31, 2003 Share Posted December 31, 2003 You got it Just by changing the values, the sounds should still have the same "pattern"...but be different in some way. More noticably if the value that is altered is the one that is saved to AUDC0 (location $15). Quote Link to comment Share on other sites More sharing options...
atwwong Posted July 12, 2004 Share Posted July 12, 2004 Since there is already a thread on this, I'd though to post this question here: Is there a way to alter the Adventure win sound to make it separate notes, i.e., like the twilight zone sound in Haunted House without causing cycle problems in the optimized code? ;Noise 0 : Game Over NoiseGameOver: LDA NoteCnt ;3 STA COLUPF ;Color-Luminance Playfield. ;3 STA AUDC0 ;Audio-Control 00 ;3 LSR ;2 STA AUDV0 ;Audio-Volume 00 ;3 LSR ;2 LSR ;2 STA AUDF0 ;Audio-Frequency 00 ;3 RTS ;6 I did change the distortion AUDC0 and note AUDF0 by using Glenn Saunder's 2600 sound chart from the Stella Archives. I added the new values after the color-luminance playfield code. LDA #$0E ;Load 0E for distortion AUC0 ;2 STA AUDC0 ;Set a Noise on Channel 00. ;3 LDA $02 ;Get Frequency 02 ;3 STA AUDF0 ;Store in Frequency for Channel 00. ;3 LDA #$1F ;1F loudest!!! ;2 STA AUDV0 ;Set Volume on Channel 00. ;3 Then I tried adding a delay routine from reading AtariArchives.org Assembly language Programming for Atari Computers (Chap 10) similar to this LDX #50 LDY #0 LOOP DEY BNE LOOP DEX BNE LOOP and turned off the sound to start a new note, but it caused the screen to flip horribly. I read somewhere in the Stella archives about making a note last for 1 second=?cycles, but no mention of how. Could someone please help me with this? Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 Since the original is just using a formula to create the win sound, the only way to change it to be an acutal musical tune would be to use the optimized code and add in a data table that holds the frequency data...then a ram location is used to hold the offset of the "note" that it is currently playing from that table. Something LIKE this... ;Noise 0 : Game Over NoiseGameOver: LDA #$05 ;distortion 5 ;2 STA AUDC0 ;Audio-Control 00 ;3 LDA #$08 ;volume level 8 ;2 STA AUDV0 ;Audio-Volume 00 ;3 LDA NoteCnt ;load note counter ;3 STA COLUPF ;Color-Luminance Playfield. ;3 TAX ;transfer the counter to X ;2 LDA NoteTbl,X ;load note from the table ;4 STA AUDF0 ;Audio-Frequency 00 ;3 RTS ;6 ;note frequency data NoteTbl: .byte (up to 256 values) I said LIKE that, since any data you enter is going to be played very fast unless additional coding is added to delay each value read from the table...and I haven't checked to see how well it works. It's just an example of using tables. And the sound registers only use the lowest 5 bits AFAIK, so the upper 3 bits of the values in the table could be used for something else (like the distortion or volume of each note). Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 Oops...I forgot to mention... You cannot use a delay loop like the one you posted. The 2600's display NEEDS to happen during all of that time you are wasting...but it cannot since you are in that loop. That gives you the garbled display you see. An alternative is to adjust the note counter at specific intervals...like every 8th or 16th display frame (which would hold notes for 8/60 or 16/60 seconds respectively). IIRC, the frame counter in Adventure is $E5. This ram location is bumped up by 1 every 60th of a second. So what you would do is only adjust NoteCnt when the frame counter is at certian values instead of all of them. BUT NoteCnt NEEDS to be able to be altered on every frame...so that normal sounds (like dragons biting you) sound correct. In order to solve this problem, you'll need to add in an additional test to check which noise is being played BEFORE the program alters NoteCnt Here's the original code of where notes are begun... ;Make A Noise. MakeSound: LDA NoteCnt ;Check Not Count. ;3 BNE MakeSound_2 ;Branch if Noise to be made.;2 STA AUDV0 ;Turn off the Volume. ;3 STA AUDV1 ;3 RTS ;6 MakeSound_2: DEC NoteCnt ;Goto the Next Note. ;5 LDA NoiseType ;Get the Noise Type. ;3 BEQ NoiseGameOver ;Game Over ;2 See what's happening? First, NoteCnt is checked to see if anything is left. If not, all sound is cleared and the routine exits. If so, it branches to the second half, and adjusts NoteCnt. Then it checks to see what noise it is. If the game is over, it branches. What you need to do is check the noise type BEFORE the NoteCnt is altered. That way, you can have it be adjusted at a different interval from normal sounds when the game is over... The first part of that problem can be solved just by swapping the order of the commands... MakeSound_2: LDA NoiseType ;Get the Noise Type. ;3 BEQ NoiseGameOver ;Game Over ;2 DEC NoteCnt ;Goto the Next Note. ;5 I just moved the DEC instruction past the noise type check. Now, the NoiseGameOver routine will need a bit of work. Remember, since the DEC command is now below the branch, it isn't adjusting NoteCnt at all yet when the end noise is played. You'll need to check the frame counter there and decide whether to adjust the NoteCnt on that frame. Squeeze these lines at the top of the NoiseGameOver routine... ;Noise 0 : Game Over NoiseGameOver: LDA FrameCnt ;load the frame counter ;3 AND #$0F ;check the lower nybble ;2 BNE NoAdjust ;if anything there,do not change;2 DEC NoteCnt ;Goto the Next Note. ;5 NoAdjust: What is happening here is that the frame counter is checked. If the lower bits hold anything at all, it branches over the adjustment done to NoteCnt. In this example, the DEC instruction will only be executed every 16/60 seconds (each note is held for $0F+1 frames...i.e. 16 frames) Also...since the NoteCnt variable is DECremented, you'll need to have your song data held in NoteTbl in reverse order. You'll also need to enter the number of values held in that table in the MainGameLoop. Original... LDA #$FF ;2 STA NoteCnt ;Set the note count to maximum;3 You'd change that #$FF value to how many notes you have in the table. So if you had 32 notes, you would use #$1F ($1F+1=$20, i.e. 32 notes) Quote Link to comment Share on other sites More sharing options...
atwwong Posted July 12, 2004 Share Posted July 12, 2004 Nukey, your coding skills are OUTSTANDING, as always! It's weird transposing notes backwards, but using: ;note frequency data NoteTbl: .byte $11;can be any filler value .byte $11,$0E,$0D,$0E,$11,$0E,$0D,$0E,$11,$0E,$0D,$0E,$11,$0E,$0D,$0E works (nice twilight zone, I may play a bit with the distortion ) when changing the number of notes to 16: BNE MainGameLoop_2 ;If Not Branch.. ;2 LDA #$10 ;Number of notes in table $FF;now 16=0F+1=10 *** NEW ;2 STA $DF ;Set the note count to maximum. ;3 STA $DE ;Set the game to inactive. ;3 LDA #$00 ;Set the noise type to end-noise. ;2 STA $E0 ;3 Note (pun not intended) that I had to add an extra value; for some reason the last note is cut during playtesting so I needed to add one more for a filler. "Glitches" that occur because of this coding are that the Colour-Luminance Playfield no longer cycles through all the colours and the select switch needs to be depressed before reseting a game, but these are VERY minor compared to the positive sound changes!!! Thanks Nukey! (This will be used in my project.) Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 The color problem can be solved easily by just using the frame counter instead of the note counter...like this edit: Change this... LDA NoteCnt ;load note counter ;3 STA COLUPF ;Color-Luminance Playfield;3 TAX ;transfer the counter to X;2 to this... LDA FrameCnt ;load frame counter ;3 STA COLUPF ;Color-Luminance Playfield;3 LDX NoteCnt ;load note counter ;3 The frame counter is changing on every frame (just like the note counter used to)...so the effect should be almost identical. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 Oh...and you are correct about the first data value (the last note played). Once the note counter becomes zero, it isn't held for 16 frames. So it IS played...but only played for a 60th of a second (so you don't even hear it unless you are Data or a canine or something. To correct this, you can either use a "throw-away" byte in the data table...or begin the data table with a value that some other table (that's just above this one) needs to end with. The latter will save you 1 byte. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 I suppose that the upper bits of the data value could be used as the note delay timer. You have 3 bits, so you could make them -close- to being half, quarter, eighth, and sixteenth notes by using 111, 011, 001, and 000 as the upper 3 bits...then LSR'ing those bits downward to be used when AND'ing the result against the frame counter. The routine that was made before starts like this... ;Noise 0 : Game Over NoiseGameOver: LDA FrameCnt ;load the frame counter ;3 AND #$0F ;check the lower nybble ;2 BNE NoAdjust ;if anything there,do not change;2 DEC NoteCnt ;Goto the Next Note. ;5 NoAdjust: Every note is a quarter note (sort of), since 16 frames are always held. But you could do this instead... (entire revised NoiseGameOver routine) ;Noise 0 : Game Over NoiseGameOver: LDX NoteCnt ;load note counter ;3 LDA NoteTbl,X ;load note from the table ;4 LSR ;shift the value downward..;2 LSR ;.. ;2 LSR ;...to remove the frequency;2 ORA #$03 ;...and always set bits 0/1;2 ;i.e. so it's always at least a sixteenth note AND FrameCnt ;check against the frame ctr;3 BNE NoAdjust ;if anything left, do not change;2 DEC NoteCnt ;Goto the Next Note. ;5 NoAdjust: LDA #$05 ;distortion 5 ;2 STA AUDC0 ;Audio-Control 00 ;3 LDA #$08 ;volume level 8 ;2 STA AUDV0 ;Audio-Volume 00 ;3 LDA FrameCnt ;load frame counter ;3 STA COLUPF ;Color-Luminance Playfield.;3 LDX NoteCnt ;load note counter ;3 LDA NoteTbl,X ;load note from the table ;4 STA AUDF0 ;Audio-Frequency 00 ;3 RTS ;6 That takes a bit longer to execute, so I'm not sure about any timing issues. Now in the data table values, you can set the higher bits depending on how long you want each note to play Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 Duh...no need to keep reloading X, since it is always the value of NoteCnt Try this instead... ;Noise 0 : Game Over NoiseGameOver: LDX NoteCnt ;load note counter ;3 LDA NoteTbl,X ;load note from the table ;4 LSR ;shift the value downward..;2 LSR ;.. ;2 LSR ;...to remove the frequency;2 ORA #$03 ;...and always set bits 0/1;2 AND FrameCnt ;check against the frame ctr;3 BNE NoAdjust ;if anything left ,do not change;2 DEX ;Goto the Next Note. ;2 ;save 3 cycles not using DEC...we'll need to save X later tho. NoAdjust: LDA #$05 ;distortion 5 ;2 STA AUDC0 ;Audio-Control 00 ;3 LDA #$08 ;volume level 8 ;2 STA AUDV0 ;Audio-Volume 00 ;3 LDA FrameCnt ;load frame counter ;3 STA COLUPF ;Color-Luminance Playfield.;3 STX NoteCnt ;save note counter ;3 ;it's still in X...so we might as well save the adjusted counter there LDA NoteTbl,X ;load note from the table ;4 STA AUDF0 ;Audio-Frequency 00 ;3 RTS ;6 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 12, 2004 Share Posted July 12, 2004 Oh...and this is probably the cause of the select glitch: You posted: BNE MainGameLoop_2 ;If Not Branch.. ;2 LDA #$10 ;# notes in table $FF...now $10 *** NEW;2 STA $DF ;Set the note count to maximum. ;3 STA $DE ;Set the game to inactive. ;3 LDA #$00 ;Set the noise type to end-noise;2 STA $E0 ;3 In the original game, #$FF is used to save to the note counter AND the active/inactive game variable $DE So you can probably correct it by reloading A with that value...just squeeze in 2 more bytes between the 2 save instructions: BNE MainGameLoop_2 ;If Not Branch.. ;2 LDA #$10 ;# notes in table $FF...now $10 *** NEW;2 STA $DF ;Set the note count to maximum. ;3 LDA #$FF ;<- load the "inactive game" value;2 STA $DE ;Set the game to inactive. ;3 LDA #$00 ;Set the noise type to end-noise;2 STA $E0 ;3 Quote Link to comment Share on other sites More sharing options...
atwwong Posted July 13, 2004 Share Posted July 13, 2004 Nukey, Thanks for keeping me up to date! (I'll try to sneak you into the new "1E" room ) Can this technique be used in a similar way to alter the other sound effects? Maybe I should take a look at the new stuff, first... Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted July 13, 2004 Share Posted July 13, 2004 Each sound effect is already called by a seperate routine...but this quick example of delay is only used on one of them (just when NoiseType=00). So if you wanted delay in other effects, CMP/Branch's would need to be put in just above that DEC instruction. I'd say that if you had more than one more of those, you'd be better off using DEC's in the routines for each sound effect (saving cycles...which might already be kind of thin using these patches). The method of grabbing frequencies from tables instead of using a formula is already outlined above...just transfer the counter to a register and use it as an offset. The important thing to remember is that you can't use loops...because the display needs to be able to happen. Update your stuff and exit. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.