Advertisement
Guest User

GFX 06-23-10 2:46

a guest
Jun 23rd, 2010
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.55 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement