logo
 drop

Main

Community

Submissions

Help

Author Topic: Doom SNES Hacking Guide/Documentation  (Read 503 times)

TheLoneSurvivor

  • Newbie
  • *
  • Posts: 12
  • Location: In your code.
  • if i am living to meme why am i dying to meme?
    • View Profile
Doom SNES Hacking Guide/Documentation
« on: December 10, 2015, 07:54:46 pm »
Ok, I have nothing better to do right now so I am going to make
a thread (this one) about how to hack Doom for the SNES and how it works (as far as I can tell)

This is purely off memory, due to the fact I have not worked on Doom SNES hacking in a little while, but I thankfully have good and reliable memory.

First of all, the SPC format used in Doom is N-SPC (The format Nintendo used for music on the SPC700 chip, this is as far as I can tell the most documented and easiest to hack of SPC formats)

If you are wondering what I mean by SPC formats, is that developers would sometimes use their own method of playing music on the SPC700, such as playing MIDI on a SNES, A notable example is Capcom, which used an SPC format called MMC5, if I remember correctly.

Why is it N-SPC, you may ask.

Well, I am no expert at the SNES but from analysis, the SPC engine seems to be similar to the one found in Super Mario World (N-SPC) because in an N-SPC format SPC file, there is a block of SPC700 ASM code starting at 0x700 in the SPC dump. The first 3 hex bytes are 20 CD FF, and when playing E1M1 in BSNES-Plus with the debugger open, viewing the SPC700 RAM, I decided to press the next code button (It finds blocks of ASM, which is impressive that it can sort it out) and I instantly noticed that one of the blocks of code it brought me to was the block at 0x700, starting with 20 CD FF. Because it is (what I can tell to be) the SPC engine, it makes sense that it would be loaded into the SPC700 RAM all the time. Second, it seems to have the same structure if not very similar structure as the N-SPC format. Third, it is licensed by Nintendo so maybe they got access to using the N-SPC format.  Last of all, the music works on all SPC players, even if they only have N-SPC support (I am almost sure, at least.)

Then comes the levels, which use a colour index for the floor and ceiling, rather than texture mapping, and the level data is similar to the original DOS data, but simplified, and made compatible with the engine used to make Doom SNES, but also to work on a SNES in the first place. The colour index for floor ceiling colours are as fallows (BTW, the sky texture is colour $FF, and thanks mopoz for the colour index and level loading asm code along with structure he posted on one of my other threads)


256 colors for the floor and ceiling.

BTW, color $FF -> F_Sky

Now here is the level loading ASM code (as far as I can tell) and some level data structures

Code: [Select]
$5F/FAF2 22 2E 31 5F JSL $5F312E[$5F:312E]   load map


$5F/312E AD D1 06    LDA $06D1  [$3F:06D1]   map number
$5F/3131 48          PHA                     A:0000 X:2806 Y:0001 P:envmxdIZc
$5F/3132 0A          ASL A                   A:0000 X:2806 Y:0001 P:envmxdIZc
$5F/3133 AA          TAX                     A:0000 X:2806 Y:0001 P:envmxdIZc
$5F/3134 4B          PHK                     A:0000 X:0000 Y:0001 P:envmxdIZc
$5F/3135 AB          PLB                     A:0000 X:0000 Y:0001 P:envmxdIZc
$5F/3136 BD 82 37    LDA $3782,x[$5F:3782]   A:0000 X:0000 Y:0001 P:envmxdIzc
$5F/3139 8F BF 06 00 STA $0006BF[$00:06BF]   A:0402 X:0000 Y:0001 P:envmxdIzc
$5F/313D BD 14 33    LDA $3314,x[$5F:3314]   A:0402 X:0000 Y:0001 P:envmxdIzc
$5F/3140 8F 80 00 70 STA $700080[$70:0080]   A:18B8 X:0000 Y:0001 P:envmxdIzc
$5F/3144 BD 4A 33    LDA $334A,x[$5F:334A]   A:18B8 X:0000 Y:0001 P:envmxdIzc
$5F/3147 8F 82 00 70 STA $700082[$70:0082]   A:37A8 X:0000 Y:0001 P:envmxdIzc
$5F/314B BD 80 33    LDA $3380,x[$5F:3380]   A:37A8 X:0000 Y:0001 P:envmxdIzc
$5F/314E 8F 84 00 70 STA $700084[$70:0084]   A:7F82 vertex add
$5F/3152 BD B6 33    LDA $33B6,x[$5F:33B6]   A:7F82 X:0000 Y:0001 P:envmxdIzc
$5F/3155 8F 8E 00 70 STA $70008E[$70:008E]   A:01CE  vertex value
$5F/3159 BD EC 33    LDA $33EC,x[$5F:33EC]   A:01CE X:0000 Y:0001 P:envmxdIzc
$5F/315C 8F 86 00 70 STA $700086[$70:0086]   A:C270 linedefs
$5F/3160 BD 22 34    LDA $3422,x[$5F:3422]   A:C270
$5F/3163 8F 90 00 70 STA $700090[$70:0090]   A:01D5  lindefs value
$5F/3167 BD 58 34    LDA $3458,x[$5F:3458]   A:01D5 X:0000 Y:0001 P:envmxdIzc
$5F/316A 8F 88 00 70 STA $700088[$70:0088]   A:D861 X:0000 Y:0001 P:eNvmxdIzc
$5F/316E BD 8E 34    LDA $348E,x[$5F:348E]   A:D861 X:0000 Y:0001 P:eNvmxdIzc
$5F/3171 8F 8A 00 70 STA $70008A[$70:008A]   A:D86B siddefs D86B+1;
$5F/3175 BD FA 34    LDA $34FA,x[$5F:34FA]   A:D86B X:0000 Y:0001 P:eNvmxdIzc
$5F/3178 8F 8C 00 70 STA $70008C[$70:008C]   A:F746 X:0000 Y:0001 P:eNvmxdIzc
$5F/317C BD 30 35    LDA $3530,x[$5F:3530]   A:F746 X:0000 Y:0001 P:eNvmxdIzc
$5F/317F 8F 94 00 70 STA $700094[$70:0094]   A:FACE Texture
$5F/3183 BD C4 34    LDA $34C4,x[$5F:34C4]   A:FACE X:0000 Y:0001 P:eNvmxdIzc
$5F/3186 8F 92 00 70 STA $700092[$70:0092]   A:02CE  texture value
$5F/318A BD D2 35    LDA $35D2,x[$5F:35D2]   A:02CE X:0000 Y:0001 P:envmxdIzc
$5F/318D 8F 9A 00 70 STA $70009A[$70:009A]   A:0055 X:0000 Y:0001 P:envmxdIzc
$5F/3191 BD 08 36    LDA $3608,x[$5F:3608]   A:0055 thing numb (thing)
$5F/3194 8F 9C 00 70 STA $70009C[$70:009C]   A:EBC2 X:0000 Y:0001 P:eNvmxdIzc
$5F/3198 BD 3E 36    LDA $363E,x[$5F:363E]   A:EBC2 things
$5F/319B 85 00         STA $00    [$00:0000]   A:EEEE
$5F/319D 18              CLC                     A:EEEE X:0000 Y:0001 P:eNvmxdIzc
$5F/319E 69 06 00     ADC #$0006              A:EEEE X:0000 Y:0001 P:eNvmxdIzc
$5F/31A1 8F 9E 00 70 STA $70009E[$70:009E]   A:EEF4 X:0000 Y:0001 P:eNvmxdIzc
$5F/31A5 BD 74 36    LDA $3674,x[$5F:3674]   A:EEF4 X:0000 Y:0001 P:eNvmxdIzc
$5F/31A8 8F A0 00 70 STA $7000A0[$70:00A0]   A:FE42
$5F/31AC BD AA 36    LDA $36AA,x[$5F:36AA]   A:FE42 X:0000 Y:0001 P:eNvmxdIzc
$5F/31AF 8F A4 00 70 STA $7000A4[$70:00A4]   A:FE83 X:0000 Y:0001 P:eNvmxdIzc
$5F/31B3 BD E0 36    LDA $36E0,x[$5F:36E0]   A:FE83 X:0000 Y:0001 P:eNvmxdIzc
$5F/31B6 8F A6 00 70 STA $7000A6[$70:00A6]   A:FE8E X:0000 Y:0001 P:eNvmxdIzc
$5F/31BA BD 16 37    LDA $3716,x[$5F:3716]   A:FE8E X:0000 Y:0001 P:eNvmxdIzc
$5F/31BD 8F A2 00 70 STA $7000A2[$70:00A2]   A:FE83 X:0000 Y:0001 P:eNvmxdIzc
$5F/31C1 BD 4C 37    LDA $374C,x[$5F:374C]   A:FE83 X:0000 Y:0001 P:eNvmxdIzc
$5F/31C4 8F A8 00 70 STA $7000A8[$70:00A8]   A:FE8E X:0000 Y:0001 P:eNvmxdIzc
$5F/31C8 8A          TXA                     A:FE8E X:0000 Y:0001 P:eNvmxdIzc
$5F/31C9 0A          ASL A                   A:0000 X:0000 Y:0001 P:envmxdIZc
$5F/31CA AA          TAX                     A:0000 X:0000 Y:0001 P:envmxdIZc
$5F/31CB BD A8 32    LDA $32A8,x[$5F:32A8]   A:0000 X:0000 Y:0001 P:envmxdIZc
$5F/31CE 8F 7C 00 70 STA $70007C[$70:007C]   A:9ED4 nodes
$5F/31D2 BD AA 32    LDA $32AA,x[$5F:32AA]   A:9ED4 X:0000 Y:0001 P:eNvmxdIzc
$5F/31D5 8F 7E 00 70 STA $70007E[$70:007E]   A:0058 X:0000 Y:0001 P:envmxdIzc
$5F/31D9 BD 66 35    LDA $3566,x[$5F:3566]   A:0058 Bank 2
$5F/31DC 8F 96 00 70 STA $700096[$70:0096]   A:E86E sectors (end $524c - stop bytes)
$5F/31E0 BD 68 35    LDA $3568,x[$5F:3568]   A:E86E X:0000 Y:0001 P:eNvmxdIzc
$5F/31E3 8F 98 00 70 STA $700098[$70:0098]   A:005B Bank for adress
$5F/31E7 85 02       STA $02    [$00:0002]   A:005B X:0000 Y:0001 P:envmxdIzc

thing #0 - #5 (1 - 4 spawn, 5 - teleport) = 8 byte (8 bit - settings; 8 bit - index things; 16 bit - X; 16 bit - Y; 16 bit - angle) 
         {Player}
things_name[$00]:='Player 1 start';         
things_name[$01]:='Player 2 start';         
things_name[$02]:='Player 3 start';         
things_name[$03]:='Player 4 start';         
things_name[$04]:='Player Deathmatch start';
        {Teleport}
things_name[$05]:='Teleport Destination';

thing #6-#$3F - 6 byte (8 bit - settings; 8 bit - index things; 16 bit - X; 16 bit - Y) 

============================================
Sector 10 byte settings
0 = sector_special; (sector_special shr 2)
1 = bright_room
2 = sector_bright_flash;
3-4 = sector_floor_height;
5-6 = sector_ceil_height
7 = sector_floor_color
8 = sector_ceil_color
9 = sector_tag
============================================
Lindefs 16 bytes settings
0-1 = linedefs_vertx_strt
2-3 = linedefs_vertx_end
4-5 = linedefs_type
6-7 = linedefs_angle
8-9 = linedefs_texture_offset
10 = linedefs_action
11 = linedefs_tag
========================================
SideDefs 12 byte
0-1 = sidedefs_vertx_strt
2-3 = sidedefs_vertx_end
4 = sidedefs_flags
5 = sidedefs_horizontal_scroll
6 = sidedefs_vertical_scroll
7-8 = sidedefs_texture_offset
9-10 = sidedefs_linedf_number
11 = sidedefs_sector_number

Credits to mopoz for the colour index and map loading ASM code and map data structure.

The sounds are normal, typical BRR samples that can be easily edited with BRR editors that work with ROMs, such as SNESSor, which I use to make SNES BRR hacks (The windows version of SNESSOR is not good, use the DOS version under DOSBox or if you want to go hardcore, even a real DOS PC to use SNESSOR, as a DOS version that is better than the windows version exists,
Some sounds are loaded into SPC, and can not be edited according to the Doomworld user ShaneAmp.

The graphics are what I know the most about, and are pretty easy once you learn where they are and what settings to use in Tile Molester (best tool for graphics hacking I have seen).

The wall textures (and sky textures) start at hex ofset 0x8000 in the ROM. In Tile Molester, I remember that textures used either 8bpp linear or 8bpp planar (8bpp is 256 colour bitplanes) (I think it was planar, if it is even called planar, but I forget and will check all of this soon.) The sprites were pretty close to the end of the ROM and were 4bpp (16 colour bitplane) linear, if I remember correctly but I am almost positive it was) and were split up, I guess they split it up so that if one part of a frame can be used for another they just use 1 part of a frame, rather than have 2 identical parts of a frame, which just wastes ROM space. The font was at the far end of the ROM almost, and was certainly 8bpp linear but you will have to hold minus quite a bit to get the rows to line up and form a clear, undivided font.

The text is the easiest part, you literally find the text you want to replace in a hex editor, and replace the text but remember that any text you add MUST be in uppercase, or the letters/numbers will be a glitchy colourful tile ingame. Your text also has a limit of the original text size, so replace your text wisely. If your text is shorter than the original text, replace the characters left over from the original text with spaces, which I have not tested but should work, considering spaces between words work (no special space code by the way, literally just hit space when making spaces.)
« Last Edit: December 11, 2015, 10:50:43 pm by TheLoneSurvivor »
Doom SNES Hacker.

mopoz

  • Jr. Member
  • **
  • Posts: 59
  • Location: Siberia
  • Russia, Vodka and Bears
    • View Profile
Re: Doom SNES Hacking Guide/Documentation
« Reply #1 on: January 20, 2016, 03:41:46 am »
Nodes E1M1
original
Code: [Select]
      Adr    X   Y   ChenX ChenY    Right BOX     Left BOX     RCHILD LCHILD
[00] $0000: 0B48 EF00 0000 0020 0B600B48EF00EFC0 0B480B28EF00EFC0 8001 8002
[01] $001C: 0B60 EF00 FFE8 0000 0B600B28EF00EFC0 0B600B28EE40EEE0 0000 8003
[02] $0038: 0B28 EFC0 0000 FF40 0B280A80EE40EFE0 0B600B28EE40EFC0 8000 0001
[03] $0054: 0B60 EFC0 00C0 0000 0C200B60EF00EFC0 0C200B60EFC0EFE0 8004 8005
[04] $0070: 0C20 EF00 FF40 0000 0C200B60EF00EFE0 0C200B60EE40EF00 0003 8006
[05] $008C: 0C38 EF20 0000 FFE0 0C380C20EF00EFC0 0C580C38EF00EFC0 8008 8009
[06] $00A8: 0C58 EF00 FFE0 0000 0C580C20EF00EFC0 0C580C20EE40EEE0 0005 800A
[07] $00C4: 0C58 EF00 0000 00C0 0D000C58EE40EFE0 0C580C20EE40EFC0 8007 0006
[08] $00E0: 0C20 EFE0 0000 FFE0 0C200B60EE40EFE0 0D000C20EE40EFE0 0004 0007
[09] $00FC: 0B60 EFE0 0000 FFE0 0B600A80EE40EFE0 0D000B60EE40EFE0 0002 0008
[0A] $0118: 0BB0 ED18 0000 FFF8 0BB00B60ED10ED18 0BD00BB0ED10ED18 800E 800F
[0B] $0134: 0BB0 ED10 0020 0000 0BD00B60ED00ED10 0BD00B60ED10ED18 800D 000A
[0C] $0150: 0BD0 ED10 0000 0008 0C200BD0ED00ED18 0BD00B60ED00ED18 800C 000B
--/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/--
[DD] $182C: FD80 F480 02C0 0080 0040FD80F1C0F500 0040FD80F480F500 00DC 80E0
[DE] $1848: 0040 F1C0 FD40 0080 0040FD80F1C0F500 0040FD80F1C0F240 00DD 80E1
[DF] $1864: FD80 F240 0000 0240 0040FD80F1C0F500 FD80FD00F1C0F500 00DE 80E2
[E0] $1880: 0040 F2C0 0040 0080 00800040F280F340 00800040F2C0F400 80E4 80E5
[E1] $189C: 0080 F380 FFC0 0080 00800040F380F440 00800040F280F400 80E3 00E0
[E2] $18B8: 0040 F500 0000 FF80 0040FD00F1C0F500 00800040F280F440 00DF 00E1
[E3] $18D4: 0080 F340 0000 0040 02C00080F280F440 0080FD00F1C0F500 00C1 00E2
[E4] $18F0: 02C0 F220 0000 00C0 0EE002C0ED00F800 02C0FD00F1C0F500 00A7 00E3

SNES
Code: [Select]
      Address  X   Y   ChenX ChenY    Right BOX   RCHILD   Left BOX      LCHILD
[00] $189ED4: F1C0 FF40 0B80 0040 0B800B80F1ABF1C0 8008 0B800AC0F1C0F230 8004
[01] $189EF0: F230 FF40 0B80 FFD0 0B800AC0F1ABF230 0000 0B800AC0F200F2E0 8000
[02] $189F0C: F1F8 0000 0D18 0018 0D190D18F1EFF1F8 8018 0D180D18F1F8F210 8014
[03] $189F28: F210 FFA8 0D18 FFD0 0D190D18F1EFF210 0038 0D180C20F1E0F2D6 8010
[04] $189F44: F240 FFA0 0D78 FFD0 0D780D18F210F240 8028 0D900CF0F210F298 8024
[05] $189F60: F298 FFA0 0D50 FFC0 0D900CF0F210F298 0070 0D500CF0F258F298 8020
[06] $189F7C: F298 FFC0 0D90 0000 0D900CF0F210F298 008C 0D900CAAF298F3A9 801C
[07] $189F98: F258 0028 0CF0 FFB8 0D900CAAF210F3A9 00A8 0D190C20F1E0F2D6 0054
[08] $189FB4: F1E0 FF60 0CC0 0040 0CC00BE7F1C0F220 802C 0D900C20F1E0F3A9 00C4
[09] $189FD0: F240 0028 0D90 FFCA 0E600DE0F211F2E2 8034 0DB80D78F20AF240 8030
[0A] $189FEC: F298 FFE8 0D90 FFA8 0E600D78F20AF2E2 00FC 0D900BE7F1C0F3A9 00E0
[0B] $18A008: F2E0 FF58 0C28 FF50 0C8F0B80F1D6F2E0 803C 0C280AC0F230F37C 8038
[0C] $18A024: F418 00E0 0AC0 FFE8 0C100AC0F400F49A 8044 0BA00AC0F360F418 8040
[0D] $18A040: F380 0098 0BA8 0080 0C400B47F380F400 804C 0D490BA8F308F420 8048
[0E] $18A05C: F400 00A8 0C40 0020 0CE80B7AF3DBF471 8050 0D490B47F308F420 016C
[0F] $18A078: F308 FED8 0CD0 0078 0CD00B00F2B4F3A8 8054 0D490B47F308F471 0188
--/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/-- --/--
[DD] $18B700: F3C0 0000 0140 0040 01400100F3C0F440 1810 01F00140F3C0F440 8384
[DE] $18B71C: F3C0 0040 0100 0000 01F00100F3C0F440 182C 01F00100F280F3C0 17F4
[DF] $18B738: F318 0000 01F0 0090 01F00100F280F440 1848 02C001F0F2E0F3E0 1730
[E0] $18B754: F3E0 0000 02C0 00A0 02C00100F280F440 1864 056002C0F1A0F657 1714
[E1] $18B770: F400 0000 0100 FFC0 05600100F1A0F657 1880 0100FD00F1C0F500 14AC
[E2] $18B78C: F380 0000 0560 0060 0560FD00F1A0F657 189C 0EE00560ED00F800 1030
If Left Child or Right Child > $7FFF then
 to go SideBase+$37A8  (analog Subsector+Segs)

Exemple
 [04] $189F44: F240 FFA0 0D78 FFD0 0D780D18F210F240 8028 0D900CF0F210F298 8024
 
 $8028+$37a8 = $B7D0  or ($b7a8 + ($8028-$8000)/4)

Code: [Select]
$5F/3144 BD 4A 33    LDA $334A,x[$5F:334A]   A:18B8 X:0000 Y:0001 P:envmxdIzc
$5F/3147 8F 82 00 70 STA $700082[$70:0082]   A:37A8

Looking $18B7d0
01 F2 00 58
01 - visible SDEFS on sector


SideBase #10
Sidedefs visible: 01
Sidedefs Offset: 00F2 ($18D95E =$18D86C+ $00F2) 
Sector Numb: 58

Code: [Select]
$5F/316E BD 8E 34    LDA $348E,x[$5F:348E]   A:D861 X:0000 Y:0001 P:eNvmxdIzc
$5F/3171 8F 8A 00 70 STA $70008A[$70:008A]   A:D86B siddefs D86B+1=D86C

If Left Child or Right Child < $8000 then
 to go Nodes+$9ed4

exemple
[03] $189F28: F210 FFA8 0D18 FFD0 0D190D18F1EFF210 0038 0D180C20F1E0F2D6 8010
$189ed4+$0038= $189F0C (N line = $0038\$1C=2)

Code: [Select]
$5F/31CB BD A8 32    LDA $32A8,x[$5F:32A8]   A:0000 X:0000 Y:0001 P:envmxdIZc
$5F/31CE 8F 7C 00 70 STA $70007C[$70:007C]   A:9ED4
[02] $189F0C: F1F8 0000 0D18 0018 0D190D18F1EFF1F8 8018 0D180D18F1F8F210 8014
« Last Edit: January 20, 2016, 04:07:26 am by mopoz »
Skate-punk rulezzzz