Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

GFX 06-23-10 2:46

By: a guest on Jun 23rd, 2010  |  syntax: None  |  size: 12.55 KB  |  views: 215  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;
  3. ;; This file installs a very complex custom GFX routine
  4. ;; to SMAS SMB1. Ths file aims at accomplishing several
  5. ;; goals:
  6. ;;
  7. ;; 1) Custom GFX per level
  8. ;;      SMAS SMB1 uses a system to insert GFX which is designed
  9. ;;      to save space. This proves inefficient to the modern hacker,
  10. ;;      so of course, making a better GFX loading system is a must.
  11. ;;
  12. ;; 2) Allowing up to 0x1000 GFX files
  13. ;;      If GFX per level routine is to be created, it is obvious that
  14. ;;      there should be more GFX to choose from. Following Lunar Magic's
  15. ;;      design, the limit will be set at 0x1000 which is more than reasonable.
  16. ;;
  17. ;; 3) LZ2 Compression
  18. ;;      Having 0x1000 GFX files exist uncompressed is a very bad idea!
  19. ;;      LZ2 Compression is a popular algorithm used by SMW, Yoshi's Island,
  20. ;;      Zelda III, and other great SNES games. SMAS does not use this, so
  21. ;;      it would be smart to implement it.
  22. ;;
  23. ;; 4) Fix several problems caused by (1) through (3)
  24. ;;      Many issues have arisen due to installing all the previous ASM hacks.
  25. ;;      Most notable are any cutscene GFX (game over, time up, prelevel scene,
  26. ;;      save princess peach scene, etc.) So we need to fix all of that.
  27. ;;
  28. ;; That is indeed a lot to cover and the length and true complexual
  29. ;; nature of the GFX.asm file (and it's sibling branches) will show
  30. ;; that.
  31. ;;
  32. ;; You can modify this, but be careful. A lot of what goes on in this
  33. ;; file is deeply integrated to other parts of the game.
  34. ;;
  35. ;; Code ©2009-2010 spel werdz rite (SWR)
  36. ;;
  37. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  38.  
  39.  
  40.  
  41. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  42. ;;
  43. ;; Definitions of stuff
  44. ;;
  45. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  46. !AnimGFX1 = $7F4000             ;\
  47. !AnimGFX2 = $7F5000             ;|RAM address locations of where
  48. !AnimGFX3 = $7F6000             ;|the animated GFX will be stored.
  49. !AnimGFX4 = $7F7000             ;/
  50.  
  51. !MainGFX = $7F8000              ;This serves as a GFX "template" when doing VRAM transfers
  52.  
  53. !PlayerGFX1 = $7F8000           ;Page 1 of the current player's GFX
  54. !PlayerGFX2 = $7F9000           ;Page 2 of the current player's GFX
  55.  
  56. !MiscGFX = $7FA000              ;Holds some extra GFX data for random cutscenes
  57. !PrincessGFX = $7FB000          ;GFX data of the "Rescue Princess" cutscene
  58.  
  59.  
  60.  
  61. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  62. ;;
  63. ;; This clears some old data and makes a
  64. ;; few modications to certain bytes, as
  65. ;; well as jump to new routines when needed.
  66. ;;
  67. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  68.  
  69. ;GFX Initialization Routine
  70. ORG $03812B
  71.         REP $59 : NOP
  72. ORG $03812B
  73.         JSL InitGFX
  74.        
  75. ORG $049266
  76.         JSL LoadCutsceneGFX
  77.  
  78. ORG $049313
  79.         ;JSL LoadNextLevelGFX
  80.  
  81. ORG $049655
  82.         REP $03 : NOP
  83.        
  84. ;Changes which address to load the Player GFX from.
  85. ORG $04D834
  86.         dw !PlayerGFX1
  87. ORG $04D847
  88.         REP $0D : NOP
  89.         LDA #$7F
  90.  
  91. ORG $04DD87
  92.         db $7F
  93. ORG $04DD9C
  94.         db $B0
  95.  
  96. ORG $04ED2E
  97.         REP $2C : NOP
  98. ORG $04ED2E
  99.         RTL
  100.  
  101. ;Changes addresses of animation frame GFX files.
  102. ORG $05E64C
  103.         db $7F
  104. ORG $05E654
  105.         db $00
  106. ORG $05E687
  107.         db $7F
  108. ORG $05E699
  109.         db $AB
  110.        
  111. ORG $05E6AF
  112.         REP $01CA : NOP
  113. ORG $05E6B1
  114.         JML LoadLevelGFX
  115.  
  116.  
  117.  
  118. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  119. ;;
  120. ;; These are some fundamental data files
  121. ;; which insert the LZ2 data and get their pointers.
  122. ;;
  123. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  124. incsrc SMB1/GFX/Files.asm
  125. incsrc SMB1/GFX/Tables.asm
  126. incsrc SMB1/GFX/Files_Locs.asm
  127. incsrc SMB1/GFX/Files_Ptrs.asm
  128.  
  129.  
  130.  
  131. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  132. ;;
  133. ;; This is the actual start of the GFX ASM hack.
  134. ;; It's a pretty big mess, but I've tried my best
  135. ;; to keep it legible.
  136. ;;
  137. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  138. ORG !GFX
  139.         incsrc SMB1/GFX/LZ2.asm
  140. DoDecompress:
  141.         LDA.l GFX_Lo,x
  142.         STA.b !LZ2_Lo
  143.         LDA.l GFX_Hi,x
  144.         STA.b !LZ2_Hi
  145.         LDA.l GFX_Bk,x
  146.         STA.b !LZ2_Bk
  147.         JMP DecompressGFXPage
  148.  
  149.  
  150.  
  151. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  152. ;;
  153. ;; This is a GFX Initialization routine. At the
  154. ;; start of a game, the standard GFX file are
  155. ;; loaded into the respective spots. This is
  156. ;; sort of the "fallback" template for all GFX.
  157. ;;
  158. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  159.         incsrc SMB1/GFX/Static.asm
  160. InitGFX:
  161.         PHB
  162.         PHP
  163.         PHK
  164.         PLB
  165.         REP #$10
  166.         SEP #$20
  167.  
  168.         LDA.b #$80                              ;\
  169.         STA.w $2115                             ;|This mostly just sets up some pre-DMA
  170.         LDA.b #$7F                              ;|trasnfer stuff, like disabling interrupts
  171.         STA.w $4304                             ;|and selecting transfer locations.
  172.         STA.b !Raw_Bk                           ;|
  173.         LDX.w #$1801                            ;|
  174.         STX.w $4300                             ;|
  175.         LDX.w #!MainGFX                         ;|
  176.         STX.b !Raw_Lo                           ;/
  177.        
  178.         LDY.w #$0010
  179. -
  180.         LDX.w InitGFX_Table1,y                  ;\
  181.         JSR DoDecompress                        ;|This nifty little loop gets the default GFX files
  182.         LDX.w InitGFX_Table2,y                  ;|from InitGFX_Table1, decompresses their GFX, stores
  183.         STX.w $2116                             ;|it !MainGFX, then sets up a DMA transfer to a location
  184.         LDX.w #!MainGFX                         ;|selected by InitGFX_Table2. The idea is to set up the
  185.         STX.w $4302                             ;|default GFX for the game.
  186.         LDX.w #$1000                            ;|See SMB1/GFX/Static.asm for tables.
  187.         STX.w $4305                             ;|
  188.         LDA.b #$01                              ;|
  189.         STA.w $420B                             ;|
  190.         REP 2 : DEY                             ;|
  191.         BPL -                                   ;/
  192.        
  193.         LDX.w #!MiscGFX                         ;\
  194.         STX.b !Raw_Lo                           ;|!MiscGFX is a RAM location with a GFX file designed to never
  195.         LDX.w #$0026                            ;|change (unless you want it to). The purpose of this DMA transer
  196.         JSR DoDecompress                        ;|is to take the 2BPP GFX from GFX file $26 and permanently save it.
  197.         LDX.w #$5000                            ;|It's used mostly in the status bar, but also for the water animation
  198.         STX.w $2116                             ;|in underwater levels.
  199.         LDX.w #!MiscGFX+$800                    ;|Because it's only $800 bytes, I'm considering making this a raw GFX
  200.         STX.w $4302                             ;|ROM location to free up some RAM. You free to modify this and do so
  201.         LDX.w #$0800                            ;|yourself. Please don't ask me how though. Like I said before, modifcation
  202.         STX.w $4305                             ;|is for experience users only.
  203.         LDA.b #$01                              ;|
  204.         STA.w $420B                             ;/
  205.        
  206.         LDY.w #$0006
  207. -
  208.         LDX.w AnimGFX_Table1,y                  ;\
  209.         STX.b !Raw_Lo                           ;|This routine is very straightforward: Load the animated GFX RAM location,
  210.         LDX.w AnimGFX_Table2,y                  ;|then the GFX file to store there, then just decompress it. Note that we're
  211.         JSR DoDecompress                        ;|not doing a DMA transfer. Just writing the animated GFX to the desired RAM location.
  212.         REP 2 : DEY                             ;|The game takes care of the actual anmation when the event occurs.
  213.         BPL -                                   ;/
  214.        
  215.         LDX.w #!PrincessGFX                     ;\
  216.         STX.b !Raw_Lo                           ;|This is also straightforward: Take GFX file $000E (saved princess cutscene GFX) and
  217.         LDX.w #$000E                            ;|save it to #!PrincessGFX. The game will load it when the even occurs.
  218.         JSR DoDecompress                        ;/
  219.        
  220.         PLP
  221.         PLB
  222.         RTL
  223.  
  224.  
  225.  
  226. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  227. ;;
  228. ;; This routine aims at inserting custom GFX
  229. ;; into the DMA when they are needed. The only
  230. ;; two cutscenes I've noticed are needed are
  231. ;; Game Over and Time Up screens.
  232. ;;
  233. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  234. LoadCutsceneGFX:
  235.         PHP
  236.         PHB
  237.         PHK
  238.         PLB
  239.         REP #$10
  240.         SEP #$20
  241.        
  242.         LDA.b #$80                              ;\
  243.         STA.w $2115                             ;|Sets up a DMA transfer for the cutscene.
  244.         LDA.b #$7F                              ;|If you are unsure why !MainGFX is always used,
  245.         STA.w $4304                             ;|it's because it's not a static RAM table. It's use
  246.         STA.w !Raw_Bk                           ;|is to have a GFX page exist for a DMA transfer, so it
  247.         LDX.w #$1801                            ;|can be used pretty much at any time. The othr RAM tables
  248.         STX.w $4300                             ;|however are supposed to be static (you can change them
  249.         LDX.w #!MainGFX                         ;|if you have a way which suites what you need done).
  250.         STX.b !Raw_Lo                           ;|
  251.         STX.w $4302                             ;/
  252.        
  253.         LDX.w #$0011                            ;GFX011 is the Game Over/Time Up GFX
  254.         JSR DoDecompress
  255.         LDX.w #$3400
  256.         STX.w $2116
  257.         LDX.w #$1000
  258.         STX.w $4305
  259.         LDA.b #$01
  260.         STA.w $420B
  261.        
  262.         LDX.w #!MainGFX+$800
  263.         STX.w $4302
  264.         LDX.w #$001B                            ;GFX01B also has Game Over/Time Up GFX
  265.         JSR DoDecompress
  266.         LDX.w #$2C00
  267.         STX.w $2116
  268.         LDX.w #$0800
  269.         STX.w $4305
  270.         LDA.b #$01
  271.         STA.w $420B
  272.        
  273.         PLB
  274.         PLP
  275.         RTL
  276.  
  277.  
  278.  
  279. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  280. ;;
  281. ;; This is the grand daddy of the custom GFX loading.
  282. ;; This routine is the core of getting all GFX from pointers
  283. ;; and loading them to their respective levels. So as
  284. ;; you will guess, it's pretty long and probably a little
  285. ;; complex. But it shouldn't be too bad to get through
  286. ;; most of it.
  287. ;;
  288. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  289. LoadLevelGFX:
  290.         PHP
  291.         PHB
  292.         PHK
  293.         PLB
  294.         REP #$10
  295.         SEP #$20       
  296.         PEI (!Raw_Lo)                           ;\
  297.         PEI (!Raw_Bk)                           ;|These values need to be re-pushed onto the stack.
  298.         PEI (!Pointer_Hi)                       ;/
  299.        
  300.         LDX.w #!MainGFX                         ;\
  301.         STX.b !Raw_Lo                           ;|Sets up !MainGFX for several DMA Transfers.
  302.         LDA.b #$7F                              ;|The objective of the following loop is to load
  303.         STA.b !Raw_Bk                           ;|the level pointer, determine the GFX file, decompress
  304.         STA.w $4304                             ;|that GFX page, and do a DMA transfer to it's respective
  305.         LDA.b #$80                              ;|location. Then repeat for all level GFX (objects and sprites).
  306.         STA.w $2115                             ;|This was not an easy algorithm to set up and I'm sure
  307.         LDX.w #$1801                            ;|it could use some work.
  308.         STX.w $4300                             ;/
  309.  
  310.         LDY.w #$000E
  311. -
  312.         REP #$30                                ;We keep the REP in the loop because the status register will change.
  313.         TYA                                     ;\
  314.         REP 7 : ASL A                           ;|The pointer is now a multiple of $100 bytes (for each loop index).
  315.         STA.b !Pointer_Lo                       ;/
  316.         LDA.w $0750                             ;\
  317.         AND.w #$007F                            ;|We now add to the pointer index the current level value.
  318.         CLC                                     ;|We're not done yet though, there are other factors at play.
  319.         ADC.b !Pointer_Lo                       ;|
  320.         STA.b !Pointer_Lo                       ;/
  321.         LDA.w $07FC                             ;\
  322.         AND.w #$0002                            ;|$07FC is the "Difficult Quest" flag. I've made some major modifications
  323.         BEQ +                                   ;|to allow for a whole new quest (set by 2 or 3). Therefore, levels in this
  324.         LDA.w #$0080                            ;|region will add $80 bytes to the index
  325.         CLC                                     ;|
  326.         ADC.b !Pointer_Lo                       ;/
  327. +
  328.         ASL A                                   ;We double the index because it's relative to words, not bytes.
  329.         TAX
  330.         LDA.l GFX_Table1,x                      ;\
  331.         CMP.w #$FFFF                            ;|A lot is going on here, so it may be a tad confusing. First, we check
  332.         BEQ +                                   ;|GFX_Tabale1 indexed by the conditions we made earlier. If the value is
  333.         AND.w #$0FFF                            ;|$FFFF, that means no value has been selected so we go to the default (which
  334.         TAX                                     ;|is selected from GFX_Table3, which matches InitGFXTable1, but with switched
  335.         BRA ++                                  ;|values to match the indexes). If it isn't $FFFF, then our value is the GFX
  336. +                                               ;|index, then we move on to decompress it.
  337.         LDX GFX_Table3,y                        ;/
  338. ++
  339.         SEP #$20                                ;This is why we keep the REP #$30 in the loop at the beginning.
  340.         JSR DoDecompress                        ;\
  341.         LDX.w GFX_Table2,y                      ;|We now have the GFX page decompressed to !MainGFX. So we look up
  342.         STX.w $2116                             ;|GFX_Table2 to determine which VRAM address we will store it to.
  343.         LDX.w #!MainGFX                         ;|The rest is just a standard DMA transfer.
  344.         STX.w $4302                             ;|
  345.         LDX.w #$1000                            ;|
  346.         STX.w $4305                             ;|
  347.         LDA.b #$01                              ;|
  348.         STA.w $420B                             ;/
  349.         REP 2 : DEY
  350.         BPL -
  351.        
  352.         REP #$30                               
  353.         LDA.w $0750                             ;Now you may be wondering what this extra routine is for when it pretty much
  354.         AND.w #$007F                            ;follows the pattern of the loop that came before it. The third GFX file in VRAM
  355.         STA.b !Pointer_Lo                       ;is the layer 2 BG for levels. In SMAS SMB1, bonus levels switch the BG if you are
  356.         LDA.w $07FC                             ;Luigi. So what this does search for a flag in the ObjGFX_Table3 table (set from $1000).
  357.         AND.w #$0002                            ;If it is set, the routine checks if luigi is playing. If both are true, it increments
  358.         BEQ +                                   ;the GFX file and selects that one instead. You can use this to your advantage. If you
  359.         LDA.w #$0080                            ;want to change the BG for when it's Luigi, make sure the next GFX file is the desired one.
  360.         CLC                                     ;You can use example of this code for other cool effects too. =P
  361.         ADC.b !Pointer_Lo              
  362. +
  363.         ASL A
  364.         TAX
  365.         LDA.w ObjGFX_Table3,x
  366.         CMP.w #$FFFF
  367.         BEQ LoadPlayerGFX
  368.         PHA
  369.         AND.w #$0FFF
  370.         TAX
  371.         PLA
  372.         AND.w #$1000
  373.         STA.w $02F8
  374.         BEQ +
  375.         LDA.w $0EC2
  376.         AND.w #$00FF
  377.         BEQ +
  378.         INX
  379. +
  380.         SEP #$20
  381.         JSR DoDecompress
  382.         LDX.w #$2000
  383.         STX.w $2116
  384.         LDX.w #!MainGFX
  385.         STX.w $4302
  386.         LDX.w #$1000
  387.         STX.w $4305
  388.         LDA.b #$01
  389.         STA.w $420B
  390.  
  391. LoadPlayerGFX:
  392.         LDY.w #$0002
  393. -
  394.         LDX.w PlayerGFX_Table1,y                ;The objective of this loop is to determine which player
  395.         STX.b !Raw_Lo                           ;is selected, obtain the GFX for said player, then store it
  396.         LDX.w PlayerGFX_Table2,y                ;!PlayerGFX1 and !PlayerGFX2. Note that the two values don't
  397.         LDA.w $0EC2                             ;mean GFX for Player 1 and Player 2 repectively. The player GFX
  398.         AND.b #$FF                              ;take two pages. So the addresses represent the first and second
  399.         BEQ  +                                  ;page respectively. Thus, it is necessarry to call this at level
  400.         LDX.w PlayerGFXTable2+4,y               ;load and not during the Initialization routine.
  401. +                                               ;This is another event when I feel I should have raw GFX and just
  402.         CPX.w #$FFFF                            ;handle it during the init routine. It would free up more RAM and
  403.         BEQ +                                   ;save on loading time.
  404.         JSR DoDecompress
  405. +
  406.         DEY
  407.         DEY
  408.         BPL -
  409.  
  410.         PLX : STX !Pointer_Hi                   ;\
  411.         PLX : STX !Raw_Bk                       ;|Pulling the orignal value back from the stack
  412.         PLX : STX !Raw_Lo                       ;/
  413.         PLB
  414.         PLP
  415.         RTL