Dans cet article, je veux démonter l'appareil interne du légendaire jeu Sonic the Hedgehog pour Sega Mega Drive, ainsi que les moyens de le modifier ou, comme on dit, le piratage. Ce jeu a environ une centaine de hacks , y compris un travail vraiment digne (comme Pana Der Hejhog ou Sonic Remastered ), et étrange et même effrayant (comme An Ordinary Sonic ROM Hack ). Pour comprendre comment les créer, vous devez comprendre comment écrire dans le langage assembleur Motorola 68K (généralement les jeux pour consoles de l'époque étaient écrits en assembleur), où obtenir la version démontée du jeu et quelle architecture a son moteur.

Le démontage des fichiers ROM pour Sega se fait à l'aide du désassembleur commercial et du débogueur IDA Pro . Ensuite, il y a un processus minutieux de marquage, de structuration et de peignage du code assembleur brut à l'aide du débogueur (et de l'ingéniosité). Ce processus nécessite une bonne compréhension des caractéristiques techniques de la plate-forme Sega Mega Drive et des jeux associés.
Heureusement, GitHub a déjà démonté et étiqueté des versions de tous les jeux de la série Sonic the Hedgehog, créées par des passionnés avec le soutien du site Web Sonic Retro . Le code source du tout premier jeu de la série est mieux marqué et structuré. Cette version du code est dans le référentiel sonicretro / s1disasm et sera analysée dans l'article.
L'immersion dans la structure interne du jouet commencera par la théorie.

Sega Mega Drive ( Sega Genesis) 32- Motorola MC68000 ( Motorola 68K) Zilog Z80 ( Z80 ). (RAM) – 64K. ( ) – 320x224 .
Motorola 68K . , . Motorola 68K Apple Macintosh.
Mega Drive Yamaha YM7101 80 . ; Sega Mega Drive " Sega Mega Drive: Video Display Processor".
AS. 82 . : ResearchGate Intel Core i7 338 .
32- : D0
–D7
. . A0
–A7
. - . A7 SP
.
. .l
(long) 32- . .w
(word) .b
(byte) 16- 8- .
Motorola 68K.
move
– .
:
move.l #48, d4
– 48 d4
.move.w d5, d6
– 16 d5
d6
.move.w #$12FF, obStatus(a0)
– 12FF , obStatus
, a0
.
, #
. #$
.
:
move.l #5, (a0)
– 5 , a0
.move.l (a1), d2
– , a1
, d2
.
(a*
).
add
– .sub
– .mulu
– ; muls
– .divu
– ; divs
– .
:
add.b #$08, d0
– 08 d0
.sub.w (v_screenposx).w, d1
– d1
v_screenposx
( 16- ).mulu.w #10, d0
– d0
10 ( d0
).divs.w #$68, d2
– d2
68 ( d2
).
jmp
, bra
– .jsr
, bsr
– , rts
– ( call
ret
x86).
:
jmp .foo
nop
.foo:
SubRoutine:
nop
rts
bsr SubRoutine
68K CCR
(Condition Code Register). cmp
, tst
btst
() , beq
, bne
, bge
, ble
.
cmp
– .tst
– .btst
– .beq
/bne
– , / .bge
/ble
– , / .
:
cmp.w #32,d0
bge.s .foo
btst #0,d0
bne.s .foo
Motorola 68K ( ) , .
s1disasm Python-, . Sonic the Hedgehog "Kosinski compression", ( ).
, , git- AS
(git checkout AS
) :
./build.py
ROM- s1built.bin
. Sega Mega Drive. macOS, , OpenEmu.
– sonic.asm
. : Zilog Z80 (WaitForZ80
), (VDPSetupGame
) . GameInit
MainGameLoop
, .
, Variables.asm
. RAM, .
v_gamemode
. :
- 00 – "Sega",
- 01 – ,
- 08 – ,
- 0C – ,
- 10 – special stage,
- 14 – "Continue",
- 18 – ,
- 1C – ,
- 8C – .
move.b #id_Sega,(v_gamemode).w
GameInit
v_gamemode
, . id_Sega
id_Title
./build.py
, , "Sega" , .
v_gamemode
, . , id_Title
GM_Title
, id_Level
– GM_Level
.
, Variables.asm
. v_sonspeedmax
, v_sonspeedacc
v_sonspeeddec
.
, Sonic_Main
, : , , :
move.w #$600,(v_sonspeedmax).w
move.w #$C,(v_sonspeedacc).w
move.w #$80,(v_sonspeeddec).w
, 256. , 0xC / 256 = 0.046875, – 0x80 / 256 = 0.5 ( ).
Mega Drive Sega 315‑5313 (Video Display Processor, VDP). VDP , vdp_data_port
vdp_control_port
. VDPSetupGame
, VDPSetupArray
. , , . , GM_Level
. VDP Sega Retro.
Low Color ( Mode Register 1 ):
Video Display Processor – background ( B) foreground ( A), , . 8x8 . ; – 4x4 . , 32x32 .
(LoadTilesAsYouMove
, DrawChunks
) (BuildSprites
) , :
, LoadTilesAsYouMove
. Sonic the Hedgehog 64x32 512x256 .
foreground- Green Hill Zone, GIF-, 5 : , , . , . , 3D- . Sonic the Hedgehog.
8192 RAM . v_objspace
. , . : , , , , , . DisplaySprite
.

64 . , , Constants.asm
. a0
. , :
ObX(a0)
, ObY(a0)
– .ObVelX(a0)
, ObVelX(a1)
– 1/256 .obHeight(a0)
, obWidth(a0)
– .obSubtype(a0)
– (: ).obStatus(a0)
– .obRoutine(a0)
– .
, X , Y, .
ExecuteObjects
. , . Object Pointers.asm
. _incObj
.
, (, , , "" ). , , obRoutine
.
SpeedToPos
. , .
: no-ring challenge
, : no-ring challenge. . , ( ).
"" – Ring_Main
(bra
) :
Ring_Main:
bra.w Ring_Delete
lea (v_objstate).w,a2
moveq #0,d0
move.b obRespawnNo(a0),d0
. "" 26 Monitor.asm
. obSubtype
1 . , 6. cmp
beq
, :
Mon_Main:
cmp.b #6,obSubtype(a0)
beq DeleteObject
addq.b #2,obRoutine(a0)
move.b #$E,obHeight(a0)
, ROM' , . GitHub. , - , .
:
, . Sonic the Hedgehog 3 – .
Sonic the Hedgehog 3
, , Sonic Retro. , , , 64 , . . 0.1875 , . , 0.75.
, , , , , "" .
"", 25 & 37 Rings.asm
. :
Ring_Index:
ptr_Ring_Main: dc.w Ring_Main-Ring_Index
ptr_Ring_Animate: dc.w Ring_Animate-Ring_Index
ptr_Ring_Collect: dc.w Ring_Collect-Ring_Index
ptr_Ring_Sparkle: dc.w Ring_Sparkle-Ring_Index
ptr_Ring_Delete: dc.w Ring_Delete-Ring_Index
: Main
– ; Animate
– ; Collect
– ; Sparkle
– ; Delete
– . , , ptr_Ring_Animate
.
obStatus
. , . obStatus
( ) . bset
, , – btst
.
Ring_Animate
, , , 64 :
Ring_Animate:
tst.b (v_shield).w
beq.s .animate
.dist_from_sonic:
move.w (v_player+obX).w,d0
sub.w obX(a0),d0
move.w (v_player+obY).w,d1
sub.w obY(a0),d1
.check_magnetised:
btst #0,obStatus(a0)
bne.s .attract
.check_near_x:
cmp.w #64,d0
bge.s .animate
cmp.w #-64,d0
ble.s .animate
.check_near_y:
cmp.w #64,d1
bge.s .animate
cmp.w #-64,d1
ble.s .animate
bset #0,obStatus(a0)
.attract:
.animate:
, , . :
if sign(obVelX) == sign(distX):
, ( Motorola 68K) , 0 , 1 – . "" – XOR (eor
Motorola 68K).
, ( ) , (0.1875 0.75) 256 ( 48 192 ).
:
.attract:
move.w #48,d4
move.w obVelX(a0),d3
eor.w d0, d3
btst #$F,d3
beq.s .x_towards
move.w #192,d4
.x_towards:
cmp.w #0,d0
bge.s .attract_x
neg d4
.attract_x:
add.w d4,obVelX(a0)
move.w #48,d4
move.w obVelY(a0),d3
eor.w d1,d3
btst #$F,d3
beq.s .y_towards
move.w #192,d4
.y_towards:
cmp.w #0,d1
bge.s .attract_y
neg d4
.attract_y:
add.w d4,obVelY(a0)
.animate:
, , SpeedToPos
:
.animate:
jsr (SpeedToPos).l
ROM , — — Sonic 3 Sonic 1!
GitHub , .
. (SonED2, Chaos), , . / Motorola 68K EASy68K, , Sega.
, , . , - , , .