don't click here

SHII, STB, PSII, GnG and S1 (Updated)

Discussion in 'Engineering & Reverse Engineering' started by JoseTB, Apr 9, 2007.

Thread Status:
Not open for further replies.
  1. JoseTB

    JoseTB

    Tech Member
    717
    59
    28
    As you might know Yuji Naka programmed other titles for the Genny other than the ones we are used to talk around here. It isn't surprising to find similarities between the engine of those and the one used in Sonic games.

    Well, I was bored so started to dig into them. And it turns out the SST is actually older than what we (or at least myself) thought. In the process I have found some other stuff, but I'll discard that for the moment, as I don't have plans to write a hacking guide for one of these games anyway.

    Aside from the similarities in the object system, there's also other stuff which I don't make mention to because I don't consider it relevant; common subroutines one would expect to find in a SDK for example.

    Space Harrier II - 1988

    Code (Text):
    1. RAM:00008966 ProcessObjects:                        ; CODE XREF: RAM:loc_6758p
    2. RAM:00008966                                        ; sub_6D56+16p ...
    3. RAM:00008966                 lea     ($FFFFE000).w,a0
    4. RAM:0000896A                 bsr.w   ExecuteObject
    5. RAM:0000896E                 lea     ($FFFFE040).w,a0
    6. RAM:00008972                 bsr.w   ExecuteObject
    7. RAM:00008976                 lea     ($FFFFE080).w,a0
    8. RAM:0000897A                 bsr.w   ExecuteObject
    9. RAM:0000897E                 lea     ($FFFFE0C0).w,a0
    10. RAM:00008982                 bsr.w   ExecuteObject
    11. RAM:00008986                 lea     ($FFFFE100).w,a0
    12. RAM:0000898A                 bsr.w   ExecuteObject
    13. RAM:0000898E                 lea     ($FFFFE140).w,a0
    14. RAM:00008992                 bsr.w   ExecuteObject
    15. RAM:00008996                 lea     ($FFFFE180).w,a0
    16. RAM:0000899A                 bsr.w   ExecuteObject
    17. RAM:0000899E                 lea     ($FFFFE1C0).w,a0
    18. RAM:000089A2                 bsr.w   ExecuteObject
    19. RAM:000089A6                 lea     ($FFFFE200).w,a0
    20. RAM:000089AA                 bsr.w   ExecuteObject
    21.  
    22. [...]
    23.  
    24. RAM:00008A16                 lea     ($FFFFE580).w,a0
    25. RAM:00008A1A                 bsr.w   ExecuteObject
    26. RAM:00008A1E                 move.b  ($FFFFF212).w,d0
    27. RAM:00008A22                 bne.w   locret_8ADE
    28. RAM:00008A26                 lea     ($FFFFE5C0).w,a0
    29. RAM:00008A2A                 bsr.w   sub_8BCE
    30. RAM:00008A2E                 lea     ($FFFFE600).w,a0
    31. RAM:00008A32                 bsr.w   sub_8BC6
    32. RAM:00008A36                 lea     ($FFFFE640).w,a0
    33. RAM:00008A3A                 bsr.w   sub_8BC6
    34. RAM:00008A3E                 lea     ($FFFFE680).w,a0
    35. RAM:00008A42                 bsr.w   sub_8BC6
    36.  
    37. [...]
    38.  
    39. RAM:00008ACE                 lea     ($FFFFEB00).w,a0
    40. RAM:00008AD2                 bsr.w   sub_8BC6
    41. RAM:00008AD6                 lea     ($FFFFEB40).w,a0
    42. RAM:00008ADA                 bsr.w   sub_8BC6
    Esentially the same as STB. sub_8BC6/sub_8BCE is similar to ExecuteObject but it doesn't actually execute the object =P it's probably used for "children" objects which are controlled by a different object or something like that.

    Code (Text):
    1. RAM:00008AE0 ExecuteObject:                      ; CODE XREF: ProcessObjects+4p
    2. RAM:00008AE0                                        ; ProcessObjects+Cp ...
    3. RAM:00008AE0
    4. RAM:00008AE0; FUNCTION CHUNK AT RAM:00008C46 SIZE 0000000C BYTES
    5. RAM:00008AE0
    6. RAM:00008AE0                 move.w  (a0),d0
    7. RAM:00008AE2                 beq.w   locret_8BC4; If object is empty, return
    8. RAM:00008AE6                 lea     (Obj_Index).l,a1; Load the 'list'
    9. RAM:00008AEC                 lsl.w   #2,d0; 1(a0) * 2 + Obj_index = where we want to jump
    10. RAM:00008AEE                 jsr     (a1,d0.w) ; jump there
    11. RAM:00008AF2                 btst   #0,2(a0)
    12. RAM:00008AF8                 bne.w   loc_8C46
    13. RAM:00008AFC                 btst   #6,2(a0)
    14. RAM:00008B02                 bne.w   loc_8B46
    15. RAM:00008B06                 move.w  $16(a0),d0
    16. RAM:00008B0A                 add.w   d0,$10(a0)
    17. RAM:00008B0E                 btst   #3,2(a0)
    18. RAM:00008B14                 beq.w   loc_8B20
    19. RAM:00008B18                 move.w  ($FFFFF10C).w,d0
    20. RAM:00008B1C                 add.w   d0,$10(a0)
    21. RAM:00008B20
    22. RAM:00008B20 loc_8B20:                            ; CODE XREF: ExecuteObject+34j
    23. RAM:00008B20                 move.w  $18(a0),d0
    24. RAM:00008B24                 add.w   d0,$12(a0)
    25. RAM:00008B28                 move.w  $1A(a0),d0
    26. RAM:00008B2C                 move.w  $14(a0),d1
    27. RAM:00008B30                 add.w   d0,d1
    28. RAM:00008B32                 cmpi.w  #$400,d1
    29. RAM:00008B36                 bcs.w   loc_8C46
    30. RAM:00008B3A                 cmpi.w  #$4000,d1
    31. RAM:00008B3E                 bcc.w   loc_8C46
    32. RAM:00008B42                 move.w  d1,$14(a0)
    33. RAM:00008B46
    34. RAM:00008B46 loc_8B46:                            ; CODE XREF: ExecuteObject+22j
    35. RAM:00008B46                 btst   #1,2(a0)
    36. RAM:00008B4C                 bne.w   locret_8BC4
    37. RAM:00008B50                 move.w  $10(a0),d0
    38. RAM:00008B54                 muls.w  #$400,d0
    39. RAM:00008B58                 divs.w  $14(a0),d0
    40. RAM:00008B5C                 addi.w  #$120,d0
    41. RAM:00008B60                 cmpi.w  #$50,d0; 'P'
    42. RAM:00008B64                 bcs.w   loc_8C46
    43. RAM:00008B68                 cmpi.w  #$200,d0
    44. RAM:00008B6C                 bcc.w   loc_8C46
    45. RAM:00008B70                 move.w  d0,$1E(a0)
    46. RAM:00008B74                 move.w  $12(a0),d0
    47. RAM:00008B78                 sub.w   ($FFFFF104).w,d0
    48. RAM:00008B7C                 move.w  $14(a0),d2
    49. RAM:00008B80                 muls.w  #$400,d0
    50. RAM:00008B84                 divs.w  $14(a0),d0
    51. RAM:00008B88                 neg.w   d0
    52. RAM:00008B8A                 add.w   ($FFFFF108).w,d0
    53. RAM:00008B8E                 cmpi.w  #$70,d0; 'p'
    54. RAM:00008B92                 bls.w   loc_8C46
    55. RAM:00008B96                 cmpi.w  #$200,d0
    56. RAM:00008B9A                 bcc.w   loc_8C46
    57. RAM:00008B9E                 subq.w  #1,d0
    58. RAM:00008BA0                 move.w  d0,$1C(a0)
    59. RAM:00008BA4                 lea     ($FFFFD000).w,a1
    60. RAM:00008BA8                 moveq   #0,d0
    61. RAM:00008BAA                 move.b  $14(a0),d0
    62. RAM:00008BAE                 asl.w   #5,d0
    63. RAM:00008BB0                 adda.l  d0,a1
    64. RAM:00008BB2                 cmpi.w  #$1E,(a1)
    65. RAM:00008BB6                 bcc.w   locret_8BC4
    66. RAM:00008BBA                 addq.w  #2,(a1)
    67. RAM:00008BBC                 moveq   #0,d1
    68. RAM:00008BBE                 move.w  (a1),d1
    69. RAM:00008BC0                 adda.l  d1,a1
    70. RAM:00008BC2                 move.w  a0,(a1)
    71. RAM:00008BC4
    72. RAM:00008BC4 locret_8BC4:                          ; CODE XREF: ExecuteObject+2j
    73. RAM:00008BC4                                        ; ExecuteObject+6Cj ...
    74. RAM:00008BC4                 rts
    75. RAM:00008BC4; End of function ExecuteObject
    Again same as STB. Nothing specially interesting aside from the fact that is there.

    Code (Text):
    1. RAM:0000924C Obj_Index:                          ; DATA XREF: ExecuteObject+6o
    2. RAM:0000924C                 bra.w   loc_8CC4
    3. RAM:0000924C; End of function sub_8C52
    4. RAM:0000924C
    5. RAM:00009250; ---------------------------------------------------------------------------
    6. RAM:00009250                 bra.w   loc_7A04
    7. RAM:00009254; ---------------------------------------------------------------------------
    8. RAM:00009254                 bra.w   loc_86D6
    9. RAM:00009258; ---------------------------------------------------------------------------
    10. RAM:00009258                 bra.w   loc_A9DE
    11. RAM:0000925C; ---------------------------------------------------------------------------
    12. RAM:0000925C                 bra.w   loc_ABC8
    13. RAM:00009260; ---------------------------------------------------------------------------
    14. RAM:00009260                 bra.w   loc_B5E0
    15. RAM:00009264; ---------------------------------------------------------------------------
    16. RAM:00009264                 bra.w   loc_B674
    17. RAM:00009268; ---------------------------------------------------------------------------
    18. RAM:00009268                 bra.w   loc_B694
    19. RAM:0000926C; ---------------------------------------------------------------------------
    20. RAM:0000926C                 bra.w   loc_B6B4
    21. RAM:00009270; ---------------------------------------------------------------------------
    22. RAM:00009270                 bra.w   loc_B6D4
    23.  
    24. [...]
    Again same as STB. But objects are actually interesting. The format has slight differences between certain objects, but most of them use what follows below:

    Code (Text):
    1. RAM:0000A742 loc_A742:                            ; CODE XREF: RAM:0000A9E8j
    2. RAM:0000A742                                        ; RAM:0000ABE0j ...
    3. RAM:0000A742                 move.w  $20(a0),d0;
    4. RAM:0000A746                 add.w   d0,d0
    5. RAM:0000A748                 add.w   d0,d0
    6. RAM:0000A74A                 jmp     (a1,d0.w)
    7. RAM:0000A74A; ---------------------------------------------------------------------------
    8.  
    9. [...]
    10.  
    11. RAM:0000A772 loc_A772:                            ; DATA XREF: RAM:loc_B5E0o
    12. RAM:0000A772                 bra.w   loc_B5EA
    13. RAM:0000A776; ---------------------------------------------------------------------------
    14. RAM:0000A776                 bra.w   loc_B628
    15. RAM:0000A77A; ---------------------------------------------------------------------------
    16. RAM:0000A77A                 bra.w   loc_B644
    17. RAM:0000A77E; ---------------------------------------------------------------------------
    18. RAM:0000A77E                 bra.w   loc_B65C
    19. RAM:0000A782; ---------------------------------------------------------------------------
    20. RAM:0000A782                 bra.w   locret_B672
    21. RAM:0000A782; ---------------------------------------------------------------------------
    22.  
    23. [...]
    24.  
    25. RAM:0000B5E0 loc_B5E0:                            ; CODE XREF: RAM:00009260j
    26. RAM:0000B5E0                 lea     (loc_A772).l,a1
    27. RAM:0000B5E6                 bra.w   loc_A742
    28. RAM:0000B5EA; ---------------------------------------------------------------------------
    29. RAM:0000B5EA
    30. RAM:0000B5EA loc_B5EA:                            ; CODE XREF: RAM:loc_A772j
    31. RAM:0000B5EA                 move.w  #$FFB0,$10(a0)
    32. RAM:0000B5F0                 move.w  #$A0,$12(a0); 'á'
    33. RAM:0000B5F6                 move.w  #$30C,4(a0)
    34. RAM:0000B5FC
    35. RAM:0000B5FC loc_B5FC:                            ; CODE XREF: RAM:0000B730j
    36. RAM:0000B5FC                 move.w  #$3F00,$14(a0)
    37. RAM:0000B602                 move.w  #$FF00,$1A(a0)
    38. RAM:0000B608                 move.b  #$62,2(a0); 'b'
    39. RAM:0000B60E                 move.w  #$4000,$E(a0)
    40. RAM:0000B614                 subq.b  #1,$38(a0)
    41. RAM:0000B618                 bne.w   locret_B626
    42. RAM:0000B61C                 addq.w  #1,$20(a0)
    43. RAM:0000B620                 move.b  #$60,2(a0); '`'
    44. RAM:0000B626
    45. RAM:0000B626 locret_B626:                          ; CODE XREF: RAM:0000B618j
    46. RAM:0000B626                 rts
    47. RAM:0000B628; ---------------------------------------------------------------------------
    48.  
    49. [...]
    The actual object starts at loc_B5E0, loc_A742 is globally used for objects with this format (probably to save some bytes), and the object modes list is separated from the object code for some reason.

    Also notice the presence of two add's instead of a bitshift in loc_A742. Naka didn't born as a genius you know =P (or the optimizations in the compiler were off for this game)

    Super Thunder blade - 1988

    The processing objects subroutine in all its glory:

    Code (Text):
    1. RAM:00005A82 ProcessObjects:                ; CODE XREF: RAM:0000144Ep
    2. RAM:00005A82                                ; RAM:00001472p ...
    3. RAM:00005A82                 lea     ($FFFFA000).w,a0
    4. RAM:00005A86                 bsr.w   ExecuteObject
    5. RAM:00005A8A                 lea     ($FFFFA040).w,a0
    6. RAM:00005A8E                 bsr.w   ExecuteObject
    7. RAM:00005A92                 lea     ($FFFFA080).w,a0
    8. RAM:00005A96                 bsr.w   ExecuteObject
    9. RAM:00005A9A                 lea     ($FFFFA0C0).w,a0
    10. RAM:00005A9E                 bsr.w   ExecuteObject
    11. RAM:00005AA2                 lea     ($FFFFA180).w,a0
    12. RAM:00005AA6                 bsr.w   ExecuteObject
    13. RAM:00005AAA                 lea     ($FFFFA1C0).w,a0
    14. RAM:00005AAE                 bsr.w   ExecuteObject
    15. RAM:00005AB2                 lea     ($FFFFA200).w,a0
    16. RAM:00005AB6                 bsr.w   ExecuteObject
    17. RAM:00005ABA                 lea     ($FFFFA240).w,a0
    18. RAM:00005ABE                 bsr.w   ExecuteObject
    19. RAM:00005AC2                 lea     ($FFFFA280).w,a0
    20. RAM:00005AC6                 bsr.w   ExecuteObject
    21. RAM:00005ACA                 lea     ($FFFFA2C0).w,a0
    22. RAM:00005ACE                 bsr.w   ExecuteObject
    23. RAM:00005AD2                 lea     ($FFFFA300).w,a0
    24. RAM:00005AD6                 bsr.w   ExecuteObject
    25. RAM:00005ADA                 lea     ($FFFFA340).w,a0
    26. RAM:00005ADE                 bsr.w   ExecuteObject
    27. RAM:00005AE2                 lea     ($FFFFA380).w,a0
    28. RAM:00005AE6                 bsr.w   ExecuteObject
    29.  
    30.     [... ... ...]
    31.  
    32. RAM:00005C6A                 lea     ($FFFFAFC0).w,a0
    33. RAM:00005C6E                 bsr.w   ExecuteObject
    34. RAM:00005C72                 lea     ($FFFFA100).w,a0
    35. RAM:00005C76                 bsr.w   ExecuteObject
    Yes, it's completely awful. I can't think of a worse way to do this. Hopefully this was in later builds replaced with a loop.

    The ExecuteObject subroutine:

    Code (Text):
    1. RAM:00005C7E ExecuteObject:                 ; CODE XREF: ProcessObjects+4p
    2. RAM:00005C7E                                ; ProcessObjects+Cp ...
    3. RAM:00005C7E
    4. RAM:00005C7E; FUNCTION CHUNK AT RAM:00005DBA SIZE 0000015A BYTES
    5. RAM:00005C7E
    6. RAM:00005C7E                 move.w  (a0),d0
    7. RAM:00005C80                 beq.w   locret_5DA0; If object is empty, return
    8. RAM:00005C84                 lea     (Obj_index).l,a1; Load the 'list'
    9. RAM:00005C8A                 lsl.w   #2,d0      ; 1(a0) * 2 + Obj_index = where we want to jump
    10. RAM:00005C8C                 jsr     (a1,d0.w)  ; jump there
    11. RAM:00005C90                 btst   #0,2(a0)     ; bitfield stuff
    12. RAM:00005C96                 bne.w   loc_5DB2
    13. RAM:00005C9A                 bclr   #7,2(a0)
    14. RAM:00005CA0                 tst.w   ($FFFFF900).w
    15. RAM:00005CA4                 bne.w   loc_5DBA
    16. RAM:00005CA8                 btst   #3,2(a0)
    17. RAM:00005CAE                 bne.s   loc_5CDE    ; Camera stuff?
    18. RAM:00005CB0                 move.l  $14(a0),d0; X and Y speed?
    19. RAM:00005CB4                 add.l   d0,$A(a0)
    20. RAM:00005CB8                 move.l  $18(a0),d0
    21. RAM:00005CBC                 add.l   d0,$E(a0)
    22. RAM:00005CC0                 move.w  $1C(a0),d0
    23. RAM:00005CC4                 move.w  $12(a0),d1
    24. RAM:00005CC8                 add.w   d0,d1
    25. RAM:00005CCA                 cmpi.w  #$400,d1
    26. RAM:00005CCE                 bcs.w   loc_5DB2
    27. RAM:00005CD2                 cmpi.w  #$4000,d1
    28. RAM:00005CD6                 bcc.w   loc_5DB2
    29. RAM:00005CDA                 move.w  d1,$12(a0)
    30. RAM:00005CDE
    31. RAM:00005CDE loc_5CDE:                          ; CODE XREF: ExecuteObject+30j
    32. RAM:00005CDE                 move.w  $A(a0),d0  ; Camera stuff?
    33. RAM:00005CE2                 add.w   ($FFFFF912).w,d0
    34. RAM:00005CE6                 muls.w  #$400,d0
    35. RAM:00005CEA                 divs.w  $12(a0),d0
    36. RAM:00005CEE                 addi.w  #$120,d0
    37. RAM:00005CF2                 cmpi.w  #$20,d0; ' '
    38. RAM:00005CF6                 bls.w   locret_5DA0
    39. RAM:00005CFA                 cmpi.w  #$220,d0
    40. RAM:00005CFE                 bcc.w   locret_5DA0
    41. RAM:00005D02                 move.w  d0,$20(a0)
    42. RAM:00005D06                 move.w  $E(a0),d0
    43. RAM:00005D0A                 sub.w   ($FFFFF904).w,d0
    44. RAM:00005D0E                 muls.w  #$400,d0
    45. RAM:00005D12                 divs.w  $12(a0),d0
    46. RAM:00005D16                 neg.w   d0
    47. RAM:00005D18                 add.w   ($FFFFF90A).w,d0
    48. RAM:00005D1C                 cmpi.w  #$78,d0; 'x'
    49. RAM:00005D20                 bls.w   locret_5DA0
    50. RAM:00005D24                 bmi.w   locret_5DA0
    51. RAM:00005D28                 cmpi.w  #$1F0,d0
    52. RAM:00005D2C                 bcc.w   locret_5DA0
    53. RAM:00005D30                 move.w  d0,$1E(a0)
    54. RAM:00005D34                 btst   #6,2(a0)
    55. RAM:00005D3A                 bne.s   loc_5D62
    56. RAM:00005D3C                 btst   #1,2(a0)
    57. RAM:00005D42                 bne.s   locret_5DA0
    58. RAM:00005D44                 lea     ($FFFFE600).w,a1
    59. RAM:00005D48                 moveq   #0,d0
    60. RAM:00005D4A                 move.b  $12(a0),d0
    61. RAM:00005D4E                 asl.w   #4,d0
    62. RAM:00005D50                 adda.l  d0,a1
    63. RAM:00005D52                 cmpi.w  #$E,(a1)
    64. RAM:00005D56                 bcc.s   loc_5D84
    65. RAM:00005D58                 addq.w  #2,(a1)
    66. RAM:00005D5A                 moveq   #0,d1
    67. RAM:00005D5C                 move.w  (a1),d1
    68. RAM:00005D5E                 adda.l  d1,a1
    69. RAM:00005D60                 move.w  a0,(a1)
    70. RAM:00005D62
    71. RAM:00005D62 loc_5D62:                          ; CODE XREF: ExecuteObject+BCj
    72. RAM:00005D62                 btst   #2,2(a0)
    73. RAM:00005D68                 bne.s   loc_5D7E
    74. RAM:00005D6A                 moveq   #0,d0
    75. RAM:00005D6C                 move.b  $12(a0),d0
    76. RAM:00005D70                 add.b   $32(a0),d0
    77. RAM:00005D74                 movea.w d0,a1
    78. RAM:00005D76                 move.b  $65E2(a1),d0
    79. RAM:00005D7A                 move.w  d0,$3A(a0)
    80. RAM:00005D7E
    81. RAM:00005D7E loc_5D7E:                          ; CODE XREF: ExecuteObject+EAj
    82. RAM:00005D7E                 bset   #7,2(a0)
    83. RAM:00005D84
    84. RAM:00005D84 loc_5D84:                          ; CODE XREF: ExecuteObject+D8j
    85. RAM:00005D84                 bclr   #7,8(a0)
    86. RAM:00005D8A                 cmpi.w  #1,($FFFFF824).w
    87. RAM:00005D90                 beq.s   loc_5DA2
    88. RAM:00005D92                 cmpi.b  #$D,$12(a0)
    89. RAM:00005D98                 bcc.s   locret_5DA0
    90. RAM:00005D9A                 bset   #7,8(a0)
    91. RAM:00005DA0
    92. RAM:00005DA0 locret_5DA0:                        ; CODE XREF: ExecuteObject+2j
    93. RAM:00005DA0                                ; ExecuteObject+78j ...
    94. RAM:00005DA0                 rts
    Ignore the parts with questions marks. What's important here is the way the engine processes the objects, which is very different from S1 as you might have guessed. There's no such thing as the object id; the SST here starts with a 16bits relative object address.

    And this is how the object list actually looks like:

    Code (Text):
    1. RAM:000066DE Obj_index:   dc.l $3030303     ; DATA XREF: ExecuteObject+6o
    2. RAM:000066DE                                ; sub_5FC2+6o
    3. RAM:000066E2; ---------------------------------------------------------------------------
    4. RAM:000066E2                 bra.w   loc_6846
    5. RAM:000066E6; ---------------------------------------------------------------------------
    6. RAM:000066E6                 bra.w   loc_6BE6
    7. RAM:000066EA; ---------------------------------------------------------------------------
    8. RAM:000066EA                 bra.w   loc_6F2E
    9. RAM:000066EE; ---------------------------------------------------------------------------
    10. RAM:000066EE                 bra.w   loc_7160
    11. RAM:000066F2; ---------------------------------------------------------------------------
    12. RAM:000066F2                 bra.w   loc_7238
    13. RAM:000066F6; ---------------------------------------------------------------------------
    14. RAM:000066F6                 bra.w   loc_72FA
    15. RAM:000066FA; ---------------------------------------------------------------------------
    16. RAM:000066FA                 bra.w   loc_7438
    17. RAM:000066FE; ---------------------------------------------------------------------------
    18. RAM:000066FE                 bra.w   loc_6D0A
    19. RAM:00006702; ---------------------------------------------------------------------------
    20. RAM:00006702                 bra.w   loc_6D90
    21.  
    22.     [... ... ...]
    Finally, an object: (this is the beginning of the player object)

    Code (Text):
    1. RAM:00006846 loc_6846:                          ; CODE XREF: RAM:000066E2j
    2. RAM:00006846                 move.w  $22(a0),d0
    3. RAM:0000684A                 asl.b   #2,d0
    4. RAM:0000684C                 jsr     loc_6852(pc,d0.w)
    5. RAM:00006850                 rts
    6. RAM:00006852; ---------------------------------------------------------------------------
    7. RAM:00006852
    8. RAM:00006852 loc_6852:
    9. RAM:00006852                 bra.w   loc_685A
    10. RAM:00006856; ---------------------------------------------------------------------------
    11. RAM:00006856                 bra.w   loc_68AA
    12. RAM:0000685A; ---------------------------------------------------------------------------
    13. RAM:0000685A
    14. RAM:0000685A loc_685A:                          ; CODE XREF: RAM:loc_6852j
    15. RAM:0000685A                 move.w  #0,$A(a0)
    16. RAM:00006860                 move.w  #$110,$E(a0)
    17. RAM:00006866                 move.w  #$400,$12(a0)
    18. RAM:0000686C                 move.b  #$C,2(a0)
    19. RAM:00006872                 move.w  #1,($FFFFF938).w
    20. RAM:00006878                 move.w  #$680,8(a0)
    21. RAM:0000687E                 move.w  #1,$22(a0)
    22. RAM:00006884                 move.w  #0,$26(a0)
    23. RAM:0000688A                 move.w  #$180,($FFFFF92C).w
    24. RAM:00006890                 tst.w   ($FFFFF824).w
    25. RAM:00006894                 bne.s   loc_689C
    26. RAM:00006896                 move.w  #$1FA,$E(a0)
    27. RAM:0000689C
    28. RAM:0000689C loc_689C:                          ; CODE XREF: RAM:00006894j
    29. RAM:0000689C                 cmpi.w  #2,($FFFFF824).w
    30. RAM:000068A2                 bne.s   loc_68AA
    31. RAM:000068A4                 move.w  #$F0,$E(a0); '­'
    32. RAM:000068AA
    33. RAM:000068AA loc_68AA:                          ; CODE XREF: RAM:00006856j
    34. RAM:000068AA                                ; RAM:000068A2j
    35. RAM:000068AA                 bsr.w   sub_6956
    36. RAM:000068AE                 bsr.w   sub_6B52
    37. RAM:000068B2                 bsr.s   sub_6900
    38. RAM:000068B4                 move.w  $26(a0),d0
    39. RAM:000068B8                 beq.s   loc_68D6
    40. RAM:000068BA                 subq.w  #1,$26(a0)
    41. RAM:000068BE                 beq.s   loc_68CE
    42. RAM:000068C0                 andi.w  #2,d0
    43. RAM:000068C4                 bne.s   loc_68CE
    44. RAM:000068C6                 move.b  #$E,2(a0)
    45. RAM:000068CC                 rts
    46.  
    47.               [... ... ...]
    Well I'm not commenting it but the similarities should be clear. Mappings are missing (done differently) in this build though.


    Phantasy Star II - 1989

    Clearly based in Super Thunder blade, but with some improvements. Let's see...

    Code (Text):
    1. RAM:00000304 ProcessObjects:                ; CODE XREF: RAM:00007478p
    2. RAM:00000304                                ; RAM:00007534p ...
    3. RAM:00000304                 lea     ($FFFFE000).w,a0
    4. RAM:00000308                 move.w  #$3F,d7; '?'
    5. RAM:0000030C
    6. RAM:0000030C loc_30C:                            ; CODE XREF: ProcessObjects+Ej
    7. RAM:0000030C                 bsr.s   ExecuteObject
    8. RAM:0000030E                 adda.w  #$40,a0; '@'
    9. RAM:00000312                 dbf     d7,loc_30C
    10. RAM:00000316                 rts
    Ah, that's much better. Let's look at the ExecuteObject subroutine:

    Code (Text):
    1. RAM:00000318 ExecuteObject:                 ; CODE XREF: ProcessObjects:loc_30Cp
    2. RAM:00000318
    3. RAM:00000318; FUNCTION CHUNK AT RAM:00006D38 SIZE 00000022 BYTES
    4. RAM:00000318
    5. RAM:00000318                 move.w  (a0),d0
    6. RAM:0000031A                 beq.w   locret_3DA; If object is empty, return
    7. RAM:0000031E                 lea     (Obj_Index).l,a1; Load the 'list'
    8. RAM:00000324                 lsl.w   #2,d0      ; 1(a0) * 2 + Obj_index = where we want to jump
    9. RAM:00000326                 jsr     (a1,d0.w)  ; jump there
    10. RAM:0000032A                 btst   #0,2(a0)     ; bitfield stuff
    11. RAM:00000330                 bne.w   loc_3DC
    12. RAM:00000334                 bclr   #7,2(a0)
    13. RAM:0000033A                 btst   #3,2(a0)
    14. RAM:00000340                 beq.w   loc_3E4
    15. RAM:00000344                 move.l  $14(a0),d0; X and Y speed?
    16. RAM:00000348                 add.l   d0,$A(a0)
    17. RAM:0000034C                 move.l  $18(a0),d0
    18. RAM:00000350                 add.l   d0,$E(a0)
    19. RAM:00000354                 move.w  $1C(a0),d0; Camera stuff?
    20. RAM:00000358                 move.w  $12(a0),d1
    21. RAM:0000035C                 add.w   d0,d1
    22. RAM:0000035E                 cmpi.w  #$400,d1
    23. RAM:00000362                 bcs.w   loc_3DC
    24. RAM:00000366                 cmpi.w  #$4000,d1
    25. RAM:0000036A                 bcc.w   loc_3DC
    26. RAM:0000036E                 move.w  d1,$12(a0)
    27. RAM:00000372                 move.w  $A(a0),d0
    28. RAM:00000376                 move.w  d0,$20(a0)
    29. RAM:0000037A                 move.w  $E(a0),d0
    30. RAM:0000037E                 subi.w  #$90,d0; 'É'
    31. RAM:00000382                 muls.w  #$400,d0
    32. RAM:00000386                 divs.w  $12(a0),d0
    33. RAM:0000038A                 neg.w   d0
    34. RAM:0000038C                 addi.w  #$D0,d0; 'ð'
    35. RAM:00000390                 cmpi.w  #$80,d0; 'Ç'
    36. RAM:00000394                 bls.w   locret_3DA
    37. RAM:00000398                 bmi.w   locret_3DA
    38. RAM:0000039C                 cmpi.w  #$180,d0
    39. RAM:000003A0                 bcc.w   locret_3DA
    40. RAM:000003A4                 move.w  d0,$1E(a0)
    41. RAM:000003A8                 btst   #1,2(a0)
    42. RAM:000003AE                 bne.s   locret_3DA
    43. RAM:000003B0                 lea     ($FFFFF000).w,a1
    44. RAM:000003B4                 moveq   #0,d0
    45. RAM:000003B6                 move.b  $12(a0),d0
    46. RAM:000003BA                 asl.w   #4,d0
    47. RAM:000003BC                 adda.l  d0,a1
    48. RAM:000003BE
    49. RAM:000003BE loc_3BE:                            ; CODE XREF: ExecuteObject+B0j
    50. RAM:000003BE                 cmpi.w  #$E,(a1)
    51. RAM:000003C2                 bcs.s   loc_3CA
    52. RAM:000003C4                 adda.w  #$10,a1
    53. RAM:000003C8                 bra.s   loc_3BE
    54. RAM:000003CA; ---------------------------------------------------------------------------
    55. RAM:000003CA
    56. RAM:000003CA loc_3CA:                            ; CODE XREF: ExecuteObject+AAj
    57. RAM:000003CA                 addq.w  #2,(a1)
    58. RAM:000003CC                 moveq   #0,d1
    59. RAM:000003CE                 move.w  (a1),d1
    60. RAM:000003D0                 adda.l  d1,a1
    61. RAM:000003D2                 move.w  a0,(a1)
    62. RAM:000003D4                 bset   #7,2(a0)
    63. RAM:000003DA
    64. RAM:000003DA locret_3DA:                    ; CODE XREF: ExecuteObject+2j
    65. RAM:000003DA                                ; ExecuteObject+7Cj ...
    66. RAM:000003DA                 rts
    The extra-processing at the end is changed, but the way the objects are used remains untouched. Here's the object 'list', nothing specially interesting.

    Code (Text):
    1. RAM:0000067E Obj_Index:   dc.l 0            ; DATA XREF: ExecuteObject+6o
    2. RAM:00000682; ---------------------------------------------------------------------------
    3. RAM:00000682                 bra.w   loc_14EE
    4. RAM:00000686; ---------------------------------------------------------------------------
    5. RAM:00000686                 bra.w   loc_15D6
    6. RAM:0000068A; ---------------------------------------------------------------------------
    7. RAM:0000068A                 bra.w   loc_1780
    8. RAM:0000068E; ---------------------------------------------------------------------------
    9. RAM:0000068E                 bra.w   loc_180A
    10. RAM:00000692; ---------------------------------------------------------------------------
    11. RAM:00000692                 bra.w   loc_1882
    12. RAM:00000696; ---------------------------------------------------------------------------
    13. RAM:00000696                 bra.w   loc_1964
    14. RAM:0000069A; ---------------------------------------------------------------------------
    15. RAM:0000069A                 bra.w   loc_19FC
    16. RAM:0000069E; ---------------------------------------------------------------------------
    17. RAM:0000069E                 bra.w   loc_1A5C
    18. RAM:000006A2; ---------------------------------------------------------------------------
    19. RAM:000006A2                 bra.w   locret_1AC8
    20. RAM:000006A6; ---------------------------------------------------------------------------
    21. RAM:000006A6                 bra.w   loc_1ACA
    22.  
    23.     [... ... ...]
    Finally let's look an object. (the beginning of the menu selection object)

    Code (Text):
    1. RAM:000014EE loc_14EE:                          ; CODE XREF: RAM:00000682j
    2. RAM:000014EE                 move.w  $22(a0),d0
    3. RAM:000014F2                 asl.b   #2,d0
    4. RAM:000014F4                 jsr     loc_14FA(pc,d0.w)
    5. RAM:000014F8                 rts
    6. RAM:000014FA; ---------------------------------------------------------------------------
    7. RAM:000014FA
    8. RAM:000014FA loc_14FA:
    9. RAM:000014FA                 bra.w   loc_1502
    10. RAM:000014FE; ---------------------------------------------------------------------------
    11. RAM:000014FE                 bra.w   loc_1538
    12. RAM:00001502; ---------------------------------------------------------------------------
    13. RAM:00001502
    14. RAM:00001502 loc_1502:                          ; CODE XREF: RAM:loc_14FAj
    15. RAM:00001502                 move.w  $E(a0),$2A(a0)
    16. RAM:00001508                 moveq   #0,d1
    17. RAM:0000150A                 move.b  $32(a0),d1
    18. RAM:0000150E                 lsl.b   #4,d1
    19. RAM:00001510                 add.w   $2A(a0),d1
    20. RAM:00001514                 move.w  d1,$E(a0)
    21. RAM:00001518                 move.b  #$30,2(a0); '0'
    22. RAM:0000151E                 move.w  #$85B6,8(a0)
    23. RAM:00001524                 move.l  #off_12B4E,4(a0)
    24. RAM:0000152C                 move.w  #1,$22(a0)
    25. RAM:00001532                 move.w  #0,($FFFFDE50).w
    26. RAM:00001538
    27. RAM:00001538 loc_1538:                          ; CODE XREF: RAM:000014FEj
    28. RAM:00001538                 tst.w   ($FFFFDE10).w
    29. RAM:0000153C                 bne.s   loc_155A
    30. RAM:0000153E                 move.w  ($FFFFDE54).w,d0
    31. RAM:00001542                 beq.s   loc_155A
    32. RAM:00001544                 tst.w   ($FFFFCC02).w
    33. RAM:00001548                 bne.s   loc_155A
    34. RAM:0000154A                 move.w  ($FFFFDE04).w,d0
    35. RAM:0000154E                 subq.w  #1,d0
    36. RAM:00001550                 lsl.w   #6,d0
    37. RAM:00001552                 addi.w  #$E000,d0
    38. RAM:00001556                 cmpa.w  d0,a0
    39. RAM:00001558                 beq.s   loc_1562
    40. RAM:0000155A
    41. RAM:0000155A loc_155A:                          ; CODE XREF: RAM:0000153Cj
    42. RAM:0000155A                                ; RAM:00001542j ...
    43. RAM:0000155A                 move.b  #$30,2(a0); '0'
    44. RAM:00001560                 rts
    Notice the presence of mappings here. But, the format used is different from the one in Sonic 1, I still have to look more around it but I know it isn't the same.

    Ghouls 'n Ghosts - 1989

    I had to add this game here in order to clarify what's up with it, but, it's not a SST based game, despite the fact of being reprogrammed by Yuji Naka. I can't fully confirm it but probably the engine which uses is actually a port of the one originally used (makes sense).

    The cheats "system", however, was directly taken from this game (after all, who would notice it? :P)

    I'm not counting other similarities with S1 such as the way the joypad is handled, the interrupts, fade in, fade out, and other common subroutines since it's most likely they were part of some sort of SDK or other common SEGA libraries.

    Sonic the hedgehog - 1991

    This is well known, but I'm adding this stuff as well to the post so you can quickly compare by yourself.

    Directly from the Hivebrain's Dissasembly:

    ProcessObjects:

    Code (Text):
    1. ROM:0000D338 ObjectsLoad:                        ; CODE XREF: ROM:00002FD6p ...
    2. ROM:0000D338                 lea     ($FFFFD000).w,a0; set address for object RAM
    3. ROM:0000D33C                 moveq   #$7F,d7
    4. ROM:0000D33E                 moveq   #0,d0
    5. ROM:0000D340                 cmpi.b  #6,($FFFFD024).w
    6. ROM:0000D346                 bcc.s   loc_D362
    7. ROM:0000D348
    8. ROM:0000D348 loc_D348:                          ; CODE XREF: ObjectsLoad+24j ...
    9. ROM:0000D348                 move.b  (a0),d0; load object number from RAM
    10. ROM:0000D34A                 beq.s   loc_D358
    11. ROM:0000D34C                 add.w   d0,d0
    12. ROM:0000D34E                 add.w   d0,d0
    13. ROM:0000D350                 movea.l Obj_Index-4(pc,d0.w),a1
    14. ROM:0000D354                 jsr     (a1)        ; run the object's code
    15. ROM:0000D356                 moveq   #0,d0
    16. ROM:0000D358
    17. ROM:0000D358 loc_D358:                          ; CODE XREF: ObjectsLoad+12j
    18. ROM:0000D358                 lea     $40(a0),a0; next object
    19. ROM:0000D35C                 dbf     d7,loc_D348
    20. ROM:0000D360                 rts
    Object list:

    Code (Text):
    1. ROM:0000D382 Obj_Index:   dc.l Obj01, ObjectFall, ObjectFall, ObjectFall
    2. ROM:0000D382                                ; DATA XREF: ObjectsLoad+18t
    3. ROM:0000D382                 dc.l ObjectFall, ObjectFall, ObjectFall, Obj08
    4. ROM:0000D382                 dc.l Obj09, Obj0A, Obj0B, Obj0C
    5.  
    6. [...]
    Random Object (Sonic at title screen)

    Code (Text):
    1. ROM:0000A61C Obj0E:                         ; DATA XREF: ROM:Obj_Indexo
    2. ROM:0000A61C                 moveq   #0,d0
    3. ROM:0000A61E                 move.b  $24(a0),d0
    4. ROM:0000A622                 move.w  Obj0E_Index(pc,d0.w),d1
    5. ROM:0000A626                 jmp     Obj0E_Index(pc,d1.w)
    6. ROM:0000A626; ---------------------------------------------------------------------------
    7. ROM:0000A62A Obj0E_Index:   dc.w Obj0E_Main-Obj0E_Index; DATA XREF: ROM:Obj0E_Indexo ...
    8. ROM:0000A62A                 dc.w Obj0E_Delay-Obj0E_Index
    9. ROM:0000A62A                 dc.w Obj0E_Move-Obj0E_Index
    10. ROM:0000A62A                 dc.w Obj0E_Animate-Obj0E_Index
    11. ROM:0000A632; ---------------------------------------------------------------------------
    12. ROM:0000A632
    13. ROM:0000A632 Obj0E_Main:                    ; DATA XREF: ROM:Obj0E_Indexo
    14. ROM:0000A632                 addq.b  #2,$24(a0)
    15. ROM:0000A636                 move.w  #$F0,8(a0)
    16. ROM:0000A63C                 move.w  #$DE,$A(a0)
    17. ROM:0000A642                 move.l  #Map_obj0E,4(a0)
    18. ROM:0000A64A                 move.w  #$2300,2(a0)
    19. ROM:0000A650                 move.b  #1,$18(a0)
    20. ROM:0000A656                 move.b  #29,$1F(a0)     
    21. ROM:0000A65C                 lea     ($A704).l,a1
    22. ROM:0000A662                 bsr.w   AnimateSprite
    23. ROM:0000A666
    24. ROM:0000A666 Obj0E_Delay:                        ; DATA XREF: ROM:Obj0E_Indexo
    25. ROM:0000A666                 subq.b  #1,$1F(a0)  
    26. ROM:0000A66A                 bpl.s   Obj0E_Wait  
    27. ROM:0000A66C                 addq.b  #2,$24(a0)
    28. ROM:0000A670                 bra.w   DisplaySprite
    29.  
    30.     [... ... ...]
    So yes, with all this, I'd say S1 was created using the Phantasy Star II engine as a base, instead of the G'nG one.

    And that's it for now. I may add more stuff if I happen to find something else worth to mention.

    PD: Sorry for the grammar, it's 5 am here and I need to sleep :/
     
  2. drx

    drx

    mfw Researcher
    2,255
    347
    63
    :rolleyes:
    Nice. I knew about the PSII stuff, but never looked into Super Thunder Blade.
     
  3. TapamN

    TapamN

    Member
    95
    1
    8
    Loop unrolling is completely awful?
     
  4. JoseTB

    JoseTB

    Tech Member
    717
    59
    28
    Well, yeah, it can be sometimes useful, but this doesn't look like it to be honest. It's more like he started which two or three objects, for which that method would've been ok, and then started to add objects until what we can see there.
     
  5. TapamN

    TapamN

    Member
    95
    1
    8
    Er... What do you mean by, "he started which two or three objects, for which that method would've been ok, and then started to add objects until what we can see there"?

    With the right compiler optimization switches (-O3 would get it for sure, but I can't look up the exact switch), the following code
    Code (Text):
    1. int I;
    2. struct STBOBJ *OBJ = 0xFFFFA000;
    3. for (I = 0; I < 64; I++)
    4.     EjectuteObject @OBJ[I];
    when compiled in GCC would generate equivalent code to what Naka uses, with no actual loop control instructions.
     
  6. Sintendo

    Sintendo

    Member
    249
    0
    16
    I don't think they used C or anything back then. They just used ASM.
     
  7. drx

    drx

    mfw Researcher
    2,255
    347
    63
    :rolleyes:
    Indeed, loop unrolling is essential to gaining speed and simplicity in many cases, but I think Naka didn't program it that way intentionally.
     
  8. TapamN

    TapamN

    Member
    95
    1
    8
    Why not?
     
  9. ICEknight

    ICEknight

    Researcher Researcher
    What about Space HArrier II? Any code similarities in there?

    EDIT: Or did Naka just program the SMS version of SH?
     
  10. Sik

    Sik

    Sik is pronounced as "seek", not as "sick". Tech Member
    6,719
    1
    0
    being an asshole =P
    Well, I know Thunder Blade is a game that requires speed. I played the MSX version and it's in 3D. Amazing how it ran at a decent speed. The MegaDrive is faster, but also a bit slow, so also it needs speed...

    But I don't see why you would unroll THAT. You would unroll something to do with the video, instead.

    EDIT: BTW, I was thinking, maybe Naka made a macro to call objects and repeated that macro a lot of times. That way he makes less mistakes, besides the code somehow looks nicer (yeah, nicer :P I did this for the interrupt tester, where all interrupts must be different).

    EDIT 2: he needs to make less mistakes? XD *fixed*
     
  11. drx

    drx

    mfw Researcher
    2,255
    347
    63
    :rolleyes:
    Well for once he changed his code? Why would he do that if he intentionally did it for speed in the first place?
     
  12. TapamN

    TapamN

    Member
    95
    1
    8
    He might have just changed his mind. He could have decided that the speed increase wasn't worth the extra code size. There's a 460 byte difference between Sonic 1 and STB's object executing code, as well as a 482 byte difference between PS2 and STB. Both of these games are far more complex than STB and would benefit from any easily saved ROM space.

    (Also, has anyone disassembled Phantasy Star 1? Even if it's on a different CPU, it'd still be interesting to see how much crossed the 8 bit barrier.)
     
  13. JoseTB

    JoseTB

    Tech Member
    717
    59
    28
    See the first post =P You were right.

    I don't know the exact release dates, but apparently the engine used is slightly earlier than the one in STB.
     
Thread Status:
Not open for further replies.