Jump to content
IGNORED

Adventure sound fx question


4ever2600

Recommended Posts

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

Link to comment
Share on other sites

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).

Link to comment
Share on other sites

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

Link to comment
Share on other sites

OUCH! :o

 

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

It worked? :P j/k

 

I think it sounds a bit flat...but it did point out another byte to save :D

 

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 6 months later...

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?

Link to comment
Share on other sites

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).

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

Nukey, your coding skills are OUTSTANDING, as always! :D

 

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. :ponder:

 

"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!!! 8) Thanks Nukey! (This will be used in my project.)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 :)

Link to comment
Share on other sites

Duh...no need to keep reloading X, since it is always the value of NoteCnt :P

 

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...