don't click here

Saxman's Sonic Boom engine

Discussion in 'Engineering & Reverse Engineering' started by saxman, Dec 4, 2014.

  1. saxman


    Oldbie Tech Member
    Saxman's Sonic Boom Engine is now on GitHub:

    Please create a new branch if you plan to make modifications!

    I think 'tedious' would apply if someone wants to use a hex editor to change the levels. On the first post of this topic, I included a link to some level format conversion tools I wrote to port Sonic 2 levels to Sonic Boom. If MainMemory adds Sonic Boom support back into his editor, then that will allow larger zones to be created. Then, the only thing to really do at that point is update my tools to be able to merge physical and visual files since there's no level editor yet that supports this concept.

    You should use it for the hacking contest next year! I would like to see how many people will pick it up.
  2. Tets


    one rude dude Oldbie
    I like what I'm seeing! This looks like a really solid base for Sonic 2 modifications, taking a serious chunk of the busywork out of the whole process and adding really cool stuff like the new level layout format on top of that. I'm very happy to see Knuckles ported in by default, I've done this myself but it's truly mind numbing work, not to mention error-prone if you're anything like me. So many hours lost, so much rage at compile errors.

    I hardly have the time anymore to hack around with Sonic games but I still want to play with this.
  3. Varion Icaria

    Varion Icaria

    He's waiting.... Tech Member
    S4: Cybernetic Outbreak
    Saxman which SH2 is doing the Kos decompression? If it's master then I may try to add PWM out of boredom to see how well it will work. Also curious question, What method did you use to get your DMA working? I use the RV bit with a RAM Run code to get my DMA working for the Player art which works well.
  4. kazblox


    Diassemblies and decompilations.
    @Varion: According to SB source, SH-2 Master does the Kosinski Decompression.
  5. saxman


    Oldbie Tech Member
    Development on the next major version is underway. Current plans for the next release:

    * Merge Sonic 1 into Saxman's Sonic Boom to create one consolidated code base from which to build Sonic 1 and 2 ROMs and allow features from each game to be mixed and matched via configurations in the "constants.asm" file.
    * Enhanced sound driver to support more sounds and add PWM support (I'm looking at you Varion, that is if you want to help with this).
    * Import the Sonic 3 objects manager for improved performance
    * Update the code to improve labeling and data organization (perhaps partially based on the current GitHub efforts)

    Those are my priorities. But I'm curious what you all would like to see in the next release. What are some things you think Saxman's Sonic Boom really needs that it doesn't currently offer?
  6. DigitalDuck


    Arriving four years late. Member
    Lincs, UK
    TurBoa, S1RL
    They all sound good to me. Will start working with it soon. :v:
  7. redquebec


    I would suggest anything related to gameplay performance first, then anything to improve the sound driver. Clownacy is currently doing a universal SOnic 2 Clone Driver, could it be a good candidate for inclusion?
  8. Clownacy


    Tech Member
    Eh, I'd rather see an improved S2 driver. I've been using one in my S2 hack for a while. The changes you can make are minimal, but they're nice. Things like removing the 'nop's from the jump tables, removing unused junk, fixing 'bugs', reducing the size of some things, even dynamic music, SFX and DAC bank selection.

    The DAC driver has a really obvious optimisation you can make to the DPCM stream loop, which makes the playback speed a bit better, consistent (the two halves of the loop use the same cycles if you use a 'nop' after the optimisation), and requires all samples' "pitch" values be increased by 1, which means you should be able to get away with higher quality samples, but I don't know if the maximum speed is beyond what the YM2612 can read. Maybe you can even merge a Mega PCM feature or two in there.

    Besides, my driver still isn't 100% accurate yet. It looks like S2's driver contains some cryptic fixes for bugs that originate in S1's driver, and I still haven't found them.

    By the way, I have a suggestion: There's the old mapping error where Knuckles moves forward when he looks up.
  9. Tets


    one rude dude Oldbie
    I've always been curious about that. When I look at Knuckles in SonMapEd that sprite doesn't appear to be misaligned at all, I never understood what causes it to shift forward that one pixel in game. Easy to fix in the mappings, but I wonder if that's actually more of a workaround than a proper fix. It just never felt right to me.
  10. Varion Icaria

    Varion Icaria

    He's waiting.... Tech Member
    S4: Cybernetic Outbreak
    Given if the S2 Sound driver's disassembly works like the S3K one in terms of compiling I can implement the PWM into the stock Sonic 2 driver and remove DAC. Though the S3K driver does allow for more customizations currently thanks to Flamewing. We restored FM6 not that long ago in that driver and I implemented PWM into my version [along side of DAC actually but that's a whole different story] Anyways it's relatively easy to setup once the Z80 driver is fully setup. just give me a shout on skype where I'm usually at and I can assist.
  11. redquebec


    DO you think its possible technically to create something hybrid if we don't plan on using the 32x? DAC playing through 32x or FM6 depending on what we plan to build?
  12. saxman


    Oldbie Tech Member
    I'm curious too -- of the new features listed on the first post, what ones are your favorite? Let me know!

    Your wish is my command. Fixed. It always bothered me when I was younger

    My preferred design approach would be to "add" PWM rather than "replace" DAC. I like backward compatibility. I will be in touch with you to try and figure out what I need to do this.
  13. redquebec


    Actually, can a best-of both worlds approach would work? Is that even feasible? Using FM6 when no 32X is present, but switch to PWM if it is? Theoricaly it seems ok, but can the Z80 driver handle that?
  14. MarkeyJester


    Time to Grow Up. Resident Jester
    Any combination is possible with little to no difficulty. I suppose what you would define as "difficult" would depend on ones knowledge, but the Z80 will handle whatever it is programmed to handle provided the programmer has brains.
  15. saxman


    Oldbie Tech Member
    I'm making a good bit of headway with moving Sonic 1 over to the Sonic Boom base. GHZ is about 90% there. Here are a couple screenshots:

    Sonic 1 style HUD. Here, we play with Sonic and Tails:

    Sonic 2 style HUD. Because it's Sonic Boom, we can easily put Knuckles in Sonic 1:

    The first release of Saxman's Sonic Boom engine was to fix a lot of bugs in Sonic 2 and enhance the underlying engine while still staying true to what made Sonic 2... well... Sonic 2!

    The main point of the next release is to give hackers all assets from Sonic 1 and 2 without having to "port" anything. Using a series of configuration settings, you can decide what assets to use from each game. Mix and match what you want. Think of it as a mega-interoperable code base for Sonic 1, Sonic 2, Sonic 1+2, Sonic 1 with a Little 2, Sonic 2 with a Dash of 1, etc.

    This is also a good opportunity to merge common code between the two games. And there's a LOT of it. Below is an example of Obj95 (the Sol badnik from HTZ). I merged it with Orbinaut, because the two are nearly the same object. For Sonic 1, it's Orbinaut. For Sonic 2, it's Sol. For complex, you control if it's Sol or Orbinaut by using the MSB of the subtype. And it works beautifully!

    KEEP IN MIND: One of my goals for the next release is to improve labeling and the overall look of the code. The below code is not exempt from that effort, so be mindful that this will be improved. Anyway, here it is in its current form:

    Code (Text):
    2. ; ----------------------------------------------------------------------------
    3. ; Object 95 - Sol (fireball-throwing orbit badnik) from HTZ
    4. ;             Orbinaut enemy (LZ, SLZ, SBZ)
    5. ; ----------------------------------------------------------------------------
    6. ; Sprite_370FE:
    7. Obj95:
    8.     moveq   #0,d0
    9.     move.b  routine(a0),d0
    10.     move.w  Orb_Index(pc,d0.w),d1
    11.     jmp Orb_Index(pc,d1.w)
    12. ; ===========================================================================
    13. Orb_Index:
    14.     dc.w Orb_Main-Orb_Index
    15.     dc.w Orb_ChkSonic-Orb_Index; 1
    16.     dc.w Orb_Display-Orb_Index; 2
    17.     dc.w Orb_MoveOrb-Orb_Index; 3
    18.     dc.w Orb_ChkDel2-Orb_Index; 4
    20. orb_parent: = $3C       ; address of parent object
    21. ; ===========================================================================
    23. Orb_Main:
    24.     if INCLUDE_SONIC_1_LEVELS == TRUE
    25.         if INCLUDE_SONIC_2_LEVELS == TRUE
    26.             btst.b  #7,subtype(a0)
    27.             beq.s   ++
    28.         endif
    30.         move.l  #(ROM_Start+Map_Orb),mappings(a0)
    31.         cmpi.b  #ZONE_ID_LZ,(Current_Zone).w
    32.         bne.s   +
    33.         move.w  #$530,art_tile(a0)  ; LZ specific code
    34.         bra.s   +++
    35. +
    36.         move.w  #$429,art_tile(a0)  ; SLZ specific code
    38.         if INCLUDE_SONIC_2_LEVELS == TRUE
    39.             bra.s   ++
    40.         endif
    41. +
    42.     endif
    44.     if INCLUDE_SONIC_2_LEVELS == TRUE
    45.         move.l  #(ROM_Start+Obj95_MapUnc_372E6),mappings(a0)
    46.         move.w  #0,art_tile(a0)     ; HTZ specific code
    47.     endif
    48. +
    49.     bsr.w   JmpTo64_Adjust2PArtPointer
    50.     ori.b   #4,render_flags(a0)
    51.     move.b  #4,priority(a0)
    52.     move.b  #$B,collision_flags(a0)
    53.     move.b  #$C,width_pixels(a0)
    55.     if INCLUDE_SONIC_2_LEVELS == TRUE
    56.         if INCLUDE_SONIC_1_LEVELS == TRUE
    57.             btst.b  #7,subtype(a0)
    58.             bne.s   +
    59.         endif
    61.         move.w  #-$40,x_vel(a0)
    62.     endif
    63. +
    64.     moveq   #0,d2
    65.     lea objoff_37(a0),a2
    66.     movea.l a2,a3
    67.     addq.w  #1,a2
    68.     moveq   #3,d1
    70. Orb_makesatellites:
    71.     bsr.w   JmpTo25_SingleObjLoad2
    72.     bne.s   Orb_fail
    73.     addq.b  #1,(a3)
    74.     move.w  a1,d5
    75.     subi.w  #$B000,d5
    76.     lsr.w   #6,d5
    77.     andi.w  #$7F,d5
    78.     move.b  d5,(a2)+
    79.     move.b  0(a0),0(a1) ; load obj95
    80.     move.b  #6,routine(a1) ; use Orb_MoveOrb routine
    81.     move.l  mappings(a0),mappings(a1)
    82.     move.w  art_tile(a0),art_tile(a1)
    83.     ori.b   #4,render_flags(a1)
    84.     move.b  #4,priority(a1)
    85.     move.b  #8,width_pixels(a1)
    86.     move.b  #3,mapping_frame(a1)
    87.     move.b  #$98,collision_flags(a1)
    88.     move.b  d2,angle(a1)
    90.     if INCLUDE_SONIC_1_LEVELS == TRUE
    91.         if INCLUDE_SONIC_2_LEVELS == TRUE
    92.             move.b  subtype(a0),subtype(a1)
    93.         endif
    94.     endif
    96.     addi.b  #$40,d2
    97.     move.l  a0,objoff_3C(a1)
    98.     dbf d1,Orb_makesatellites ; repeat sequence 3 more times
    100. Orb_fail:
    101.     moveq   #1,d0
    102.     btst    #0,status(a0)   ; is orbinaut facing left?
    103.     beq.s   Orb_noflip      ; if not, branch
    104.     neg.w   d0
    106. Orb_noflip:
    107.     move.b  d0,objoff_36(a0)
    108.     move.b  subtype(a0),routine(a0) ; if type is 02, skip Orb_ChkSonic
    109.     andi.b  #$E,routine(a0)
    110.     addq.b  #2,routine(a0)
    111.     move.w  #-$40,x_vel(a0) ; move orbinaut to the left
    112.     btst    #0,status(a0)   ; is orbinaut facing left?
    113.     beq.s   Orb_noflip2     ; if not, branch
    114.     neg.w   x_vel(a0)       ; move orbinaut to the right
    116. Orb_noflip2:
    117.     rts
    118. ; ===========================================================================
    120. Orb_ChkSonic:   ; Routine 2
    121.     move.w  (MainCharacter+x_pos).w,d0
    122.     sub.w   x_pos(a0),d0    ; is Sonic to the right of the orbinaut?
    123.     bcc.s   Orb_isright     ; if yes, branch
    124.     neg.w   d0
    126. Orb_isright:
    127.     cmpi.w  #$A0,d0         ; is Sonic within $A0 pixels of orbinaut?
    128.     bcc.s   Orb_animate     ; if not, branch
    129.     move.w  (MainCharacter+y_pos).w,d0
    130.     sub.w   y_pos(a0),d0    ; is Sonic above the orbinaut?
    131.     bcc.s   Orb_isabove     ; if yes, branch
    132.     neg.w   d0
    134. Orb_isabove:
    135.     cmpi.w  #$50,d0
    136.     bcc.s   Orb_animate
    137.     tst.w   (Debug_placement_mode).w
    138.     bne.s   Orb_animate
    139.     move.b  #1,anim(a0)
    141. Orb_animate:
    142.     if INCLUDE_SONIC_2_LEVELS == TRUE
    143.         if INCLUDE_SONIC_1_LEVELS == TRUE
    144.             btst.b  #7,subtype(a0)
    145.             bne.s   +
    146.         endif
    148.         bsr.w   JmpTo26_ObjectMove
    149.         lea (ROM_Start+Ani_Orb).l,a1
    150.         bsr.w   JmpTo25_AnimateSprite
    151.         andi.b  #3,mapping_frame(a0)
    152.         bra.w   JmpTo39_MarkObjGone
    153.     endif
    154. +
    155.     if INCLUDE_SONIC_1_LEVELS == TRUE
    156.         lea (ROM_Start+Ani_Orb).l,a1
    157.         bsr.w   JmpTo25_AnimateSprite
    158.         bra.w   Orb_ChkDel
    159.     endif
    160. ; ===========================================================================
    162. Orb_Display:    ; Routine 4
    163.     bsr.w   JmpTo26_ObjectMove
    165.     if INCLUDE_SONIC_2_LEVELS == TRUE
    166.         if INCLUDE_SONIC_1_LEVELS == TRUE
    167.             btst.b  #7,subtype(a0)
    168.             bne.s   +
    169.         endif
    171.         lea (ROM_Start+off_372E0).l,a1
    172.         bsr.w   JmpTo25_AnimateSprite
    173.         andi.b  #3,mapping_frame(a0)
    174.         bra.w   JmpTo39_MarkObjGone
    175. +
    176.     endif
    178.     if INCLUDE_SONIC_1_LEVELS == TRUE
    179. Orb_ChkDel:
    180.         move.w  x_pos(a0),d0
    181.         andi.w  #$FF80,d0
    182.         sub.w   (Camera_X_pos_coarse).w,d0
    183.         cmpi.w  #OBJECT_X_SCOPE,d0
    184.         bhi.w   Orb_chkgone
    185.         jmp DisplaySprite
    187. Orb_chkgone:
    188.         lea (Object_Respawn_Table).w,a2
    189.         moveq   #0,d0
    190.         move.b  respawn_index(a0),d0
    191.         beq.s   loc_s1_11E34
    192.         bclr    #7,2(a2,d0.w)
    194. loc_s1_11E34:
    195.         lea $37(a0),a2
    196.         moveq   #0,d2
    197.         move.b  (a2)+,d2
    198.         subq.w  #1,d2
    199.         bcs.s   Orb_Delete
    201. loc_s1_11E40:
    202.         moveq   #0,d0
    203.         move.b  (a2)+,d0
    204.         lsl.w   #6,d0
    205.         addi.l  #Object_RAM&$FFFFFF,d0
    206.         movea.l d0,a1
    207.         jsr DeleteObject2
    208.         dbf d2,loc_s1_11E40
    210. Orb_Delete:
    211.         jmp DeleteObject
    212.     endif ;if INCLUDE_SONIC_1_LEVELS == TRUE
    213. ; ===========================================================================
    215. Orb_MoveOrb:    ; Routine 6
    216.     if INCLUDE_SONIC_2_LEVELS == TRUE
    217.         if INCLUDE_SONIC_1_LEVELS
    218.             btst.b  #7,subtype(a0)
    219.             bne.s   +
    220.         endif
    222.         lea (ROM_Start+off_372E0).l,a1
    223.         bsr.w   JmpTo25_AnimateSprite
    224.     endif
    225. +
    226.     movea.l orb_parent(a0),a1 ; a1=object
    227.     cmpi.b  #$95,0(a1)
    228.     bne.w   JmpTo65_DeleteObject
    229.     cmpi.b  #2,mapping_frame(a1)
    230.     bne.s   Orb_circle
    231.     cmpi.b  #$40,angle(a0)
    232.     bne.s   Orb_circle
    233.     addq.b  #2,routine(a0)
    235.     if INCLUDE_SONIC_2_LEVELS == TRUE
    236.         if INCLUDE_SONIC_1_LEVELS == TRUE
    237.             btst.b  #7,subtype(a0)
    238.             bne.s   +
    239.         endif
    241.         move.b  #0,anim(a0)
    242.     endif
    243. +
    244.     subq.b  #1,objoff_37(a1)
    245.     bne.s   Orb_fire
    246.     addq.b  #2,routine(a1)
    248. Orb_fire:
    249.     move.w  #-$200,x_vel(a0)
    250.     btst    #0,status(a1)
    251.     beq.s   Orb_noflip3
    252.     neg.w   x_vel(a0)
    254. Orb_noflip3
    255.     bra.w   JmpTo45_DisplaySprite
    256. ; ===========================================================================
    258. Orb_circle:
    259.     move.b  angle(a0),d0
    260.     jsr (ROM_Start+CalcSine).l
    261.     asr.w   #4,d1
    262.     add.w   x_pos(a1),d1
    263.     move.w  d1,x_pos(a0)
    264.     asr.w   #4,d0
    265.     add.w   y_pos(a1),d0
    266.     move.w  d0,y_pos(a0)
    267.     move.b  objoff_36(a1),d0
    268.     add.b   d0,angle(a0)
    269.     bra.w   JmpTo45_DisplaySprite
    270. ; ===========================================================================
    272. Orb_ChkDel2:
    273.     bsr.w   JmpTo26_ObjectMove
    274.     tst.b   render_flags(a0)
    275.     bpl.w   JmpTo65_DeleteObject
    277.     if INCLUDE_SONIC_2_LEVELS == TRUE
    278.         if INCLUDE_SONIC_1_LEVELS == TRUE
    279.             btst.b  #7,subtype(a0)
    280.             bne.s   +
    281.         endif
    283.         lea (ROM_Start+off_372E0).l,a1
    284.         bsr.w   JmpTo25_AnimateSprite
    285.     endif
    286. +
    287.     bra.w   JmpTo45_DisplaySprite
    288. ; ===========================================================================
    289. ; animation script
    291. Ani_Orb:
    292.     dc.w Ani_Orb_normal-Ani_Orb
    293.     dc.w Ani_Orb_angry-Ani_Orb; 1
    294. Ani_Orb_normal:
    295.     dc.b  $F,  0,$FF
    296. Ani_Orb_angry:
    297.     dc.b  $F,  1,  2,$FE,  1
    298.     even
    300.     if INCLUDE_SONIC_2_LEVELS == TRUE
    301. ; animation script
    302. off_372E0:
    303.     dc.w byte_372E2-off_372E0
    304. byte_372E2:
    305.     dc.b   5,  3,  4,$FF
    306.     even
    308.     endif
    309. ; ----------------------------------------------------------------------------
    310. ; sprite mappings
    311. ; ----------------------------------------------------------------------------
    312.     if INCLUDE_SONIC_1_LEVELS == TRUE
    313. Map_Orb:    BINCLUDE    "mappings/sprite/obj95_1.bin"
    314.     even
    315.     endif
    317.     if INCLUDE_SONIC_2_LEVELS == TRUE
    318. Obj95_MapUnc_372E6: BINCLUDE "mappings/sprite/obj95_2.bin"
    319.     endif
  16. Hitaxas


    Retro 80's themed Twitch streamer ( on hiatus) Member
    I had been pretty much away for about 2 months, which put my project on ice. But now I am back and I come back to this? I'm excited. I had restarted my hack from scratch recently using the 2007 disassembly and was in the process of doing a few things already done in your Sonic Boom engine. So naturally I've decided to scrap what little I had done and move over to this engine (of course improving on some small things and fixing more bugs as I go). I fully support this project and any further work you will do with it.

    Question though, even though your plans for the next release is to merge Sonic 1 and 2 into the same source/engine... might there be plans down the road sometime to do the same with Sonic 3/ Sonic & Knuckles?
  17. Clownacy


    Tech Member
    Instead of outright denying the ability to place objects in debug mode while dead, how about adding a different workaround that allows the placement, without the crashing? Also, some other REV00 goodies, like Obj74 and Obj66 being visible in debug placement mode? Also, what of doing what REV02 did, and removing all of the JmpTos?

    Speaking of, where'd that line about 'adda.w invincibility_time(a6),a1' come from? That's not there in REV02 or KiS2.
  18. saxman


    Oldbie Tech Member
    I meant to comment on this earlier. As it has been said, anything is technically possible. My plan would be to have the extra values and such available only in the 32X port. So it would be one code base with compiler checks to include/exclude certain things, much like I'm currently working on with the Sonic 1 and Sonic 2 stuff.

    Great! Any bugs or problems you have specific to Sonic Boom, let me know.

    I have given some thought to Sonic 3K. I'm open to the idea. I have also thought about Sonic CD and how it might be interesting to support it on the Genesis. Or, maybe allow Sonic Boom to compile for the Sega CD and do a more natural port of Sonic CD that way. There's a couple avenues to look at. But for certain, I don't want to stop after Sonic 1. Any preferences on this front?

    That's interesting. I may just put that debug placement solution in the next major release, or maybe even slip it in a patch release for v1.00.

    And yes, I definitely gave consideration to see the invisible objects (Obj03 is another good one). I wasn't sure quite how to do it though, so it got pushed to the back burner. I'd still like to do that though.

    As for the line you referenced, I think what I meant to write is Rev01 rather than Rev02. In my head I know it's the second release of Sonic 2, and so I have a habbit of immediately thinking 'revision 02', even though that's obviously wrong. If I remember correctly, Knuckles in Sonic 2 changed that line, and I couldn't understand why. I went with speculative reasoning that if it was changed, it was probably to fix something. But because I wasn't 100% sure, I left the original line there in the comment. If you or anyone else knows what the purpose of the change might be, I'm interested in hearing about it.
  19. DigitalDuck


    Arriving four years late. Member
    Lincs, UK
    TurBoa, S1RL
    Personally, I'd stick with one at a time - make this as good as you can first before going on to something else.

    Unless you're going to be able to cram S1/2/3K in one ROM with this, then I'd go for SMD support of Sonic CD first. It seems to be the natural next step.
  20. Blastfrog


    See ya starside. Member
    Saxman, this is really awesome and I love every aspect of this project from the concept to the execution. If my coding skills were up to snuff, I'd have tried the same thing; a unified, polished/bug-fixed yet faithful version of the disassemblies, for community use. The thing I like most about it is the attempt to establish some kind of base standard so that hackers can focus on what they want to/are good at without having to worry about handling the commonly expected bug-fix/extra feature checklist. It's a goddamn waste of time to redo what's already been done but better, so why not just have those expected assembly changes be accessible by default?

    It probably has a lot to do with how the different companies themselves handle their properties, but I've always preferred the creative culture on the Doom side of things than the Sonic side of things. People in the Doom community are by default very friendly and willing to lend a hand up so that every person can shine in their area of skill. It's a communal effort, those that have skill in some areas help those that are stronger in others, and the result is a collective higher quality in projects. Here, though, the default seems to be a far more private, secretive "do it yourself noob" attitude, with attempted justification being some form of disdain for "plebians" doing "distasteful" things with advanced code features as if that was some kind of problem to express one's self creatively no matter the quality. No harm in sharing your code as long as its users give due credit.

    I hope that this project shifts that attitude more toward an open-source, communal philosophy wherever that more 'elitist' mentality may exist. I haven't seen a whole lot of it at all lately, but I'm not really around here much these days. We're all 'thieves' anyway by having these disassemblies. People here help each other out anyway, I just wish that selfish "my code!" mentality didn't exist at all even in the past, given how hypocritical it is.

    Yes, CD seems a better next step than 3K given that it is mostly a souped-up S1, whereas 3K made fundamental changes to many, many things. I personally consider Sonic 3 Complete the definitive version of 3K, and I know there are reservations about sharing the source to respect the vast number of external contributors the project has seen, playing it safe to ensure that no one's contributions are shared without express permission. If 3K support is ever added to Boom, I think it should be based on S3C if negotiations can be worked out.