News:

Don't forget to visit the main site! There's lots of helpful docs, patches, and more!

Main Menu

[SM] Custom PLM Creation Help

Started by XinoeA, September 04, 2017, 05:40:44 AM

Previous topic - Next topic

XinoeA

Howdy folks,

Decided to get back to tinkering with ASM whilst slowly learning how Super Metroid ticks on the inside.

As a learning exercise I'm trying to make Air Shot blocks useful by turning them into reverse shot blocks. (Starts as air that you can shoot to turn the block solid for a few seconds before going back to air)

I've looked at the disassembly for Shot Blocks which I'm using as the basis to invert:

[spoiler]
PLMD064: : %rename(D064)    ;1x1 Respawning shot block reaction
DW SetupCE6B, InstCADF
SetupCE6B:  ;Set block type to solid, store type and new graphic to 1E17
LDX $1C87, Y
LDA $7F0002, X
AND #$F000
ORA #$0052
STA $1E17, Y
AND #$8FFF
STA $7F0002, X
RTS

InstCADF:
DW IPlaySound2Now : DB $0A
DW $0004 : DW DrawA345
DW $0004 : DW DrawA34B
DW $0004 : DW DrawA351
DW $0180 : DW DrawA357
DW $0004 : DW DrawA351
DW $0004 : DW DrawA34B
DW $0004 : DW DrawA345
DW IDrawPLM1E17 ;Routine 8B17
DW IKill ;Routine 86BC
[/spoiler]

I've currently got my code as follows:

[spoiler]
LoROM

org $949EC8 ;Patch into BTS 11
DW $84F000

org $84F000
DW $84CE6B ; Call the first routine for Shot Blocks
DW $84F004

org $84F004
DW $8C46 : DB $0A   ;Play the block break sound.
DW $0004 : DW $A351 ;Animate breaking block in reverse
DW $0004 : DW $A34B ;^
DW $0004 : DW $A345 ;^
DW $0004 : DW $8B17 ; Draw Solid Block
DW $0004 : DW $A345
DW $0004 : DW $A34B
DW $0004 : DW $A351
DW $0004 : DW $A357
DW $8486BC ; Kill PLM
RTS
[/spoiler]

Few questions from the tinkering:

I'm not sure if I can call routines CE6B and 8B17 where they are or if I need to code those sections myself. I noticed that there's a routine at B3C1 that can set blocks solid (or to air) which would be useful, not sure if I need that if I'm doing it myself.

How are the graphics assigned to be drawn? Do the A345, A34B and A351 routines just correspond to the transition tiles or are they assigned to those locations when the PLM is called/created? If it's the former, is there a routine for each block and how can I tell which is which?

Anyhow, any assistance or pointers in the right direction would be greatly appreciated!

P.JBoy

Looks good so far. Looks like you can call $CE6B and $8B17 just fine. Those drawing instructions $A345, $A34B, $A351 will be drawing the three crumbling tiles at the position where the PLM is. The format of drawing commands is simple: [number of blocks] [blocks] [X offset] [Y offset] repeat. Number of blocks is a two-byte value, X and Y offsets are one byte and each block (there are [number of blocks] of them) is two bytes. The draw instruction will draw those blocks as a row starting from the position of the PLM, then the X and Y offsets are added to the PLM's position for the purposes of processing the next row of blocks (doesn't physically change the position of the PLM). You process as many rows as you need to and then specify X offset = Y offset = 00 to end the drawing command.

Extra detail: actually if the number of blocks has bit 7 set, then the blocks will be drawn as columns from the current position (and the number of blocks will be calculated with bit 7 cleared).
...

XinoeA

Ahhaaa! Thanks for that. I understand block drawing now.

For posterity reasons:

[spoiler]
The crumbling block transition is the following:

[spoiler]
;22345
DrawA345:
DW $0001 : DW $0053
DW $0000

;2234B
DrawA34B:
DW $0001 : DW $0054
DW $0000

;22351
DrawA351:
DW $0001 : DW $0055
DW $0000
[/spoiler]

The $0053, $0054 and $0055 correspond to the block on the Tile Table. You can find the value of the block you want to draw by opening the Tileset Editor and clicking on a block. You'll see it come up as Tile $XXX. In Smile RF that's under the Copy, Paste and Save buttons.
[/spoiler]

So I have the block drawing as it should now, but it seems I will need to custom code the switch in block type from Air to Solid as the current routines have some functionality I don't want (8B17 draws the Shot Block tile because it's set by $CE6B).

Which address handles this and what's the format of changing it. Is it in the same order as in Kejardon's block documents? (0 - Air, 1 - Slope, etc etc) If I have to assign a block type would it be #$0008 at the address to convert to Solid and #$0000 for Air?

P.JBoy

The type of the block (0 - Air, 1 - Slope) is actually the top 4 bits of the definition of the block. 0053h is an air block, 8053h is a solid block, 1053h is a slope. If you want code to change the block type, the typical process is: block & 0FFFh | t000h where t is the new type. Generally speaking, if t is a kind of air block, then t + 8 is a similar kind of solid block, so you'll see a lot of routines that keep that solidity information too by doing: block & 7FFFh | t000h where t = 0 or t = 8 for air or solid respectively
...

XinoeA

Ohhhhh, duhhh. I should've realised that! :lol:

Awesome, reverse Shot Blocks are operational!

[spoiler]
;---------------------
; Reverse Shot Blocks v1
; Author - AeoniX
;---------------------

LoROM

org $949EC8 ; (Air) Shot React BTS 11
DW $84F000 ; Free space. Repoint whereever.

org $84F000
DW SetupPLM
DW $84F004

org $84F004
DW $848C46 : DB $0A ; Play the block break sound.
; V Animate breaking block in reverse
DW $0004 : DW Draw25 : DW $0004 : DW Draw50 : DW $0004 : DW Draw75
DW $0180 : DW Draw100
; V Animate breaking block
DW $0004 : DW Draw75 : DW $0004 : DW Draw50 : DW $0004 : DW Draw25
DW $848B17 ; Draw the PLM
DW $8486BC ; Kill PLM

SetupPLM:
LDX $1C87, Y
LDA $7F0002, X
AND #$4000
ORA #$00FF
STA $1E17, Y
AND #$0FFF
ORA #$4000
STA $7F0002, X
RTS

Draw100:
DW $0001 : DW $8052
DW $0000

Draw75:
DW $0001 : DW $8053
DW $0000

Draw50:
DW $0001 : DW $8054
DW $0000

Draw25:
DW $0001 : DW $8055
DW $0000
[/spoiler]

So now I'd like to have different timers on the blocks.

If I LDX $6402, Y will that give me the BTS value of the block?

I'd like to point different values of the Shot react table to the same area of code (I love code re-usability) to feed it different BTS values then calculate some duration based off that.

Thanks heaps for the help as well, very much appreciated!