Sonic and Sega Retro Message Board: fuzzbuzz - Viewing Profile - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help

Group:
Tech Member: Tech Members
Active Posts:
625 (0.15 per day)
Most Active In:
Engineering & Reverse Engineering (204 posts)
Joined:
13-November 03
Profile Views:
1658
Last Active:
User is offline Jan 10 2013 08:00 PM
Currently:
Offline

My Information

Age:
29 years old
Birthday:
August 25, 1985
Gender:
Male Male
Location:
Here
Interests:
Lots. Like ASM programming, C programming, VB programming, Video Games, Sonic...

Previous Fields

Project:
Many Many Programming/hacking tools...
National Flag:
None

Latest Visitors

Topics I've Started

  1. Sonic The Hedghog Xbox 360 Playable DEMO!!

    27 September 2006 - 01:09 PM

    That's right! Want to play Sonic the Hedgehog for the xbox360 a little early?

    Go to the xBox360 Marketplace and download the demo for free. It's 350 MB, and I'm downloading it right now, I'll be sure to let you know if it was worth it :)

    Ah, I love my 360.
  2. People who use SOME Editor

    26 September 2006 - 03:29 PM

    I'm in need of someone to do me a HUGE favor.

    I need someone to export several YMX files, consisting of voices that conform to the General Midi (GM) standard. It certainly doesn't need to be all of the voices, but definately the essentials.

    something like: "Piano, Guitar, Distorted Guitar, Bass, etc.."

    In case you're wondering why, I'll tell you. Before I implement a piano roll into SOME for direct music editing, since there are already so many MIDI editors out there, I'm implementing MIDI importing. Because Instrument Info is stored into a midi file, I can speed up inporting by having the program automaticlly choose the voice from a standard set.
  3. I've never spotted this before

    26 September 2006 - 12:34 PM

    Now, I know that I just don't notice things, but regarless, I feel obligated to post this.

    So I was looking around http://sega-16.com/V...l%20Archive.php and I decided to watch the Sonic 1 american Commercial. La dee Dah. Then I saw this:

    Posted Image
    It's in GHZ act 1, the huge S tunnel, where there's normally half as many rings and a progress marker

    Okay, so it's not the first time that I've seen something different from the final release game in a magazine or commercial. But the thing that I wonder, is that this commercial is advertising buying the game, because it's already out. I mean, they're offereing it free with the genesis, and the footage they have isn't in from the release.

    Not a breakthrough, but certainly nothing short of interesting
  4. PSG Instruments Explained (68K Alert)

    12 June 2006 - 05:08 PM

    $719A4 is the master pointer list for what is in the Nemesis Disassembly as the PSG Pointer Index. Following that are the actual PSG Instruments (I refer to them as Voices):

     PSG_Inst_Index: dc.l PSG1, PSG2, PSG3, PSG4, PSG5, PSG6, PSG7, PSG8, PSG9
     PSG1:           dc.b $00,$00,$00,$01,$01,$01,$02,$02,$02,$03,$03,$03,$04,$04,$04,$05; 0
                     dc.b $05,$05,$06,$06,$06,$07,$80; 16
     PSG2:           dc.b $00,$02,$04,$06,$08,$10,$80; 0
     PSG3:           dc.b $00,$00,$01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07; 0
                     dc.b $80                   ; 16
     PSG4:           dc.b $00,$00,$02,$03,$04,$04,$05,$05,$05,$06,$80; 0
     PSG6:           dc.b $03,$03,$03,$02,$02,$02,$02,$01,$01,$01,$00,$00,$00,$00,$80; 0
     PSG5:           dc.b $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$01,$01,$01,$01,$01; 0
                     dc.b $01,$01,$01,$01,$01,$01,$01,$01,$02,$02,$02,$02,$02,$02,$02,$02; 16
                     dc.b $03,$03,$03,$03,$03,$03,$03,$03,$04,$80; 32
     PSG7:           dc.b $00,$00,$00,$00,$00,$00,$01,$01,$01,$01,$01,$02,$02,$02,$02,$02; 0
                     dc.b $03,$03,$03,$04,$04,$04,$05,$05,$05,$06,$07,$80; 16
     PSG8:           dc.b $00,$00,$00,$00,$00,$01,$01,$01,$01,$01,$02,$02,$02,$02,$02,$02; 0
                     dc.b $03,$03,$03,$03,$03,$04,$04,$04,$04,$04,$05,$05,$05,$05,$05,$06; 16
                     dc.b $06,$06,$06,$06,$07,$07,$07,$80; 32
     PSG9:           dc.b $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F; 0
                     dc.b $80                   ; 16
    


    If you know how the PSG works, it may seem like voices are impossible when compared to the YM2612 FM voices. The FM voices uses registers in the physical chip to emulate an instrument. The different values of the registers make the sound that's being emulated different. Some of the registers include how fast the sound reaches the maximum volume and then decays, as well as a frequency register, which is where you tell the chip a Hz value, which is really just a note, like C# for example. Using different algorthms and feedback values, the chip is able to emulate a sound that is somewhat recognizable to a physical instrument. On the flip side, the PSG chip, it has basically 2 registers: the frequency register and the volume register. So without all these other complicated registers that the FM chip has, how is a PSG Voice even possible?

    Well, it's actually pretty simple. The PSG Voices are really just crude envelopes. Each byte in the PSG voice is just an amount that the Volume of the PSG Tone Generator will be changed. So, take PSG2 for example. Each cycle of the Sound Driver, the volume of the PSG is changed by 00, then 02, then 04, then 06. You've reached the end of the voice when you reach $80. I'm going to try and walk you through the routine to maybe make it a little easier to understand.

    This isn't the full routine step by step but it is the basic concept that we're really looking for. HandlePSGVoice, as I've named it, only takes one parameter. A5 is the location in memory to where the current PSG Channel's data is being stored.
     HandlePSGVoice:
                     tst.b   $B(a5)             ; Test the voice number
                     beq.w   _ExitHandleVoice   ; If it's empty, exit
    

    This is pretty self explanitory. (A5 + $B) is where the voice number is stored for reference in memory. It's voice 0-9, any of the above PSG channels. If no voice is selected (0), then the routine is exited from. Now, this beginning of the function is called each cycle by the main "HandlePSGChan", which is just several calls to KeyOn, KeyOff, and parse the actual channel data to see if a rest is being played, or a note, or a coordination flag.
     _LoadVoiceRt:                              ;
                     move.b  9(a5),d6           ; Copy the Base Volume into D6
                     moveq   #0,d0              ; Clear D0
                     move.b  $B(a5),d0          ; Move the current voice setting into D0
                     beq.s   UpdatePSGVolume    ; If there's no voice selected, just update the volume
    

    This is next part is called in two cases. Firstly, when the actual music track is being loaded, each channel is initialized. When the PSG channel is first initialized, the Base Volume is copied to D6, and then thevoice that was stored for the channel when the PSG variables were initialized (in $B(a5)) is moved into D0. The beq.s UpdatePSGVolume is only called if no voice was selected or $B(a5) is equal to 0. Otherwise, the Sound Engine needs to start handling the PSG Voice and figure out what to do with it.
                     movea.l (Off_PSGInst_Ptr).l,a0; Point A0 to the PSG Instrument pointer index
                     subq.w  #1,d0              ; Subtract from the voice value
                     lsl.w   #2,d0              ; Multiply it by 4 (Long Word pointers)
                     movea.l (a0,d0.w),a0       ; Choose the instrument from the pointer index accordingly
    

    First, the PSG voice needs to be grabbed from the ROM. THis is done using pointers. The Off_PSGInst_Ptr, is the main list of PSG Voice pointers. It's simply a list of word longs that point to the data of each voice. If you remember from the last bit of code, the voice number from $b(a5) was stored in D0. D0 needs to be decremented by 1 and then multiplied by 4 before we can used Pointer Offsets to set A0 to the beginning of the selected PSG Voice. Why? In computers, they don't start counting at 1, they start counting at 0. So when you're asking for Voice number one, to the computer, you're asking for voice number 0. Also, the voice number needs to be multiplied by 4 because we're dealing with Long Word pointers, which are four bytes in size. To get to each pointer in the Off_PSGInst_Ptr offset list, we need to go four bytes each time to the next one. Finally, whatever number voice we want is stored into A0.
                     move.b  $C(a5),d0          ; Move the PSG Voice Index Pointer (VIP) into D0
                     move.b  (a0,d0.w),d0       ; Insert that value (A0 + D0 (our current pointer to the
                                                ;   location in the PSG Voice)) into D0
                     addq.b  #1,$C(a5)          ; Increment the Voice Pointer
                     btst    #7,d0              ; If D0 is >= $80 (the end of the voice data)
                     beq.s   _EvalVoice         ; Jump if it's not
                     cmpi.b  #$80,d0            ; If it's equal to $80
                     beq.s   _EndOfVoiceData    ; Exit the function, and prevent the pointer from incrementing
                                                ;      past the current voice data
    

    $C(a5) is the current position in the voice. So, when we first start off, it's equal to 0. The next cycle, 1. The next, 2, etc... We copy the current position into D0, and then we take (A0(Our pointer to the PSG Voice)+D0(Our Current Position in the PSG Voice)) and copy what it contained there and put it in D0. Then, we increment the current location in the voice ($C(a5)) so that we handle the next byte next time. If the 7th bit of D0 is 1 (10000000), then the data is equal to $80, and that's the end of the PSG voice. If we've reached that, we jump down to _EndOFVoiceData, which simply decrements $C(a5) so that each time this is run, the computer will see we're at the end of the PSGVOice, and then keep us there everytime until a new note is played.
     _EvalVoice:                                ;
                     add.w   d0,d6              ; Add the VoiceValueModifier to the Base Volume
                     cmpi.b  #$10,d6            ; Compare 10 to D6
                     bcs.s   UpdatePSGVolume    ; If it's >= 10, branch
                     moveq   #$F,d6             ; Set D6 to $0000000F (muting the current PSG Channel)
    

    So, this is the very difficult code that makes it all happen. Okay, so it's not difficult at all. Not even confusing. What it does, is it adds the Voice Value to the Base Volume. And that is what creates the envelope. Wow, kids. Then, there's a comparison done. If D6 is greater than $10, we actually update the volume, which executes the voice and makes is happen. Now, why only if D6 is greater than $10? Well, if the PSG channel is not being used in a track, its base volume is equal to $00. Values in a PSG voice are not expected to be greater than $F, so if you add $F to $00, it's less than $10. Then, if it is infact less than 10, we set D6 to $F. You'll find out why next.
     UpdatePSGVolume:                           ;
     loc_7297C:                                 ;
                     or.b    1(a5),d6           ; OR the Channel Modifier to the new Volume
                     addi.b  #$10,d6            ; Add $10 to D6 (Increases the Channel Value to Attenuation from Frequency)
                     move.b  d6,($C00011).l     ; Write value to the PSG Port
    
     _ExitHandleVoice:                          ; Return
                     rts
    

    There are first a few checks of the channel's status byte that I've cut out because they aren't important. If any of them were true, the voice wouldn't be executed and we'd just exit the function. What we do is "OR" D6 with 1(a5) which is actually the channel modifier. The channel modifier is just a value that tells us what channel we're in. It's not as easy as channel 1, 2, or 3, however. Channel 1 = $80, Channel 2 = $A0, and Channel 3 = $C0. When we OR D6 with the channel modifier, we get a special Byte that the PSG can read and handle. For example, if in the last set of code, D6 was less than $10, the byte that we would have for channel 1 would be $8F. The left nybble being the channel number, the right nybble being the attenuation of the channel; $F being muted and $0 being the loudest.
    Then, we add $10 to D6. That increases the channel numbers $80->$90, $A0->$B0, and $C0->$D0. Each channel has 2 seperate registers, the first one (ex $80) is for the frequency and the second on (ex $90) is for the volume, or attenuation. Once the byte is ready to be sent to the PSG, it is, and then cycle by cycle, as you play the game, the voice is all fancied up for the PSG.

    This may not seem like much, but this is extrememly important to the whole music driver. If you want to know what I'm talking about set bytes $719CC-$719AC to $00. Without these envelopes, the PSG instruments wouldn't have decay rates, and the music would not only sound bland, but it sounds plain weird. Seriously, check it out for yourself. LZ is The best example. I urge you to listen to it, it's quite hilarious.

    So, nothing breakthrough, but it's one of the many interesting things I wanted to share with you guys about the Sonic 1 music Driver. I understand almost all of it, but it's really the time that it takes explaining it like this that's the killer. I can hopefully answer any of your questions you guys have.
  5. In search of...

    08 June 2006 - 07:11 PM

    Quote

    One variation of the Genesis deserves special mention, and that is the Sega TeraDrive. This was an ordinary AMD 386SX-25 PC clone with 1MB of RAM and a 40 MB hard drive, but it also included a built-in MegaDrive as a 16-bit ISA card. The original Japanese TeraDrive was black in color and vended by Sega in conjunction with a now-unknown Japanese company for use by MegaDrive developers. It shipped with a software development kit (SDK) which made it possible to develop your MegaDrive and Mega CD games (the Mega CD accessory appears to have been an option). The Teradrive eventually found its way outside of Japan in late 1993 under the sponsorship of Amstrad, the noted computer system vendor. They changed the case color to cream, beefed up the memory to 2 MB, and made the MegaDRive SDK optional. The unit wasn't very successful regardless of market, and this was largely due to its high price (about US$3000). A souped-up version called the MegaPlus was later offered based on a 486DX-33 CPU machine with 4 MB of RAM, but very few seem to have made it out the door. The TeraDrive and its successor have all but disappeared with the passage of time.


    I had no idea that the TeraDrive included a SDK. I did some research and apparently it's the same SDK that was given to developers. I wish I had known before, I found a teradrive on ebay forever ago, and I was like "Man, who'd want to own something like that"

Friends

fuzzbuzz hasn't added any friends yet.