***Lab 1: BTSD Blocks***


pL1.0

Yay, the first lab! You get to learn how to make a block. (Note that this is only for Blocktool Super Deluxe, often shortened to BTSD, because it is better than the original Blocktool and easier to work with.) For starters, if you don't have BTSD, you can download it here: http://www.smwcentral.net/download.php?id=161&type=tools. Once you have that tool, however you got it, go to the “asm” folder and open the file called “baseblock”. (It may say “baseblock.asm”.) It should say the following:


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall


MarioAbove:

LDY #$10 ;act like tile 130

LDA #$30

STA $1693

MarioBelow:

MarioSide:

SpriteV:

SpriteH:

MarioCape:

MarioFireBall:

RTL


See those JMPs at the top? In a BTSD block, those must always be there, always in that particular order, and always at the top of the file. Now, the actual names of the labels don't matter; although the default is


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall


, you could just as easily have


JMP PlayerTouchB: JMP PlayerTouchA: JMP PlayerTouchS: JMP SpriteTouchY: JMP SpriteTouchX: JMP PlayerTouchC: JMP PlayerTouchF


JMP Label1: JMP Label2: JMP Label3: JMP Label4: JMP Label5: JMP Label6: JMP Label7:


or even


JMP Apples: JMP Pears: JMP Oranges: JMP Grapefruits: JMP Pomegranates: JMP Starfruits: JMP Kumquats:


. Just make sure to keep track of them. The seven labels in this table are called “offsets”; they run certain codes depending on where the player touches the block. On a whim, let's make a block that gives Mario 1 coin if he touches it from either side, 2 coins if he touches it from above, and 3 coins if he touches it from below.


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall


MarioBelow:


LDA #$03

STA $13CC

RTL


MarioAbove:


LDA #$02

STA $13CC

RTL


MarioSide:


LDA #$01

STA $13CC

RTL


SpriteV:

SpriteH:

MarioCape:

MarioFireball:

RTL


Looks okay, right? If Mario touches the block from below, the first section of code runs and gives him 3 coins. If he touches the block from above, the next section of code runs and gives him 2 coins. If he touches it from the side, the next section of code runs and gives him 1 coin. If Mario's cape, Mario's fireball, or a sprite touches the block, it won't do anything. However, this isn't the most efficient code; it can be optimized a bit. For starters, the second-to-last RTL is unnecessary; the “MarioSide:” code goes to the RTL at the end anyway. So we can use this instead:


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall


MarioBelow:


LDA #$03

STA $13CC

RTL


MarioAbove:


LDA #$02

STA $13CC

RTL


MarioSide:


LDA #$01

STA $13CC


SpriteV:

SpriteH:

MarioCape:

MarioFireball:

RTL


We have cut out the redundant RTL. We can do more, though. Notice how all three codes end with “STA $13CC RTL”. Well, why not have only one STA $13CC and just jump to that when we need to? We would have this code:


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall


MarioBelow:


LDA #$03

BRA StoreCoins


MarioAbove:


LDA #$02

BRA StoreCoins


MarioSide:


LDA #$01


StoreCoins:


STA $13CC


SpriteV:

SpriteH:

MarioCape:

MarioFireball:

RTL


The first two codes load the number of coins we want to give into A, and then they both jump to the part of the code where A is actually stored. The third code doesn't need the BRA, since the coin-storing code comes directly afterward.


pL1.1

Now, I could technically end the lesson here; once you understand the format, making blocks is pretty easy. But there are a couple of things you will find useful when making blocks. First of all, the RAM address $1693 controls what a block acts like...well, part of it, anyway. $1693 holds the low byte, which could be pretty anything from 00 to FF. The high byte is determined by whatever is in Y when the block's code ends. If, for example, you want a block to be solid from the sides only, you can start by making it act like tile 25 in Lunar Magic's Map16 editor, which will make is act like a blank tile. BUT...remember, you don't want it to be passable from the sides. So take your seven labels:


MarioBelow:

MarioAbove:

MarioSide:

SpriteV:

SpriteH:

MarioCape:

MarioFireball:


and rearrange them a bit so they look like this:


MarioSide:

MarioBelow:

MarioAbove:

SpriteV:

SpriteH:

MarioCape:

MarioFireball:


Notice how the “MarioSide:” label is on top. Now, we can leave six of the seven labels alone, since the block is still supposed to act like a blank tile. But we want the block to activate the code that will turn it solid when the player touches it from the sides. So we can do this:


MarioSide:


LDY #$01

LDA #$30

STA $1693


MarioBelow:

MarioAbove:

SpriteV:

SpriteH:

MarioCape:

MarioFireball:


The LDY #$01 can go before the LDA, after the LDA but before the STA, or after the STA. It doesn't really matter. But this is not yet a complete block; we still need to add the jumps and the RTL. If we make this into a complete block, the .asm file should look something like this:


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall


MarioSide:


LDY #$01

LDA #$30

STA $1693


MarioBelow:

MarioAbove:

SpriteV:

SpriteH:

MarioCape:

MarioFireball:


RTL


Fair warning when using $1693, though: it seems to be impossible to make it act like anything on page 0. Oh, you can certainly write it in the code; if you want the tile to act like a door, for example, the code for that would be LDY #$00 LDA #$20 STA $1693. But for some strange reason, Map16 tiles from 0000-FFFF don't seem to work with $1693. If you want to make something passable, i.e. act like a blank tile, you can LDY #$01 LDA #$F0 (tile 1F0 is walk-through dirt in most, if not all, tilesets) instead of LDY #$00 LDA #$25. But if you happen to want a tile to act like water (tile 2), lava (tile 5), a vine (tile 6), or a coin (tile 2B)...well, you're pretty much out of luck. Yes, I know it sucks.


pL1.2

THIS JUST IN! Extra! Extra! smkdan has made a new version of BTSD with more offsets! Alert the press! The good old seven-offset blocks work fine, but guess what, SMW hacking is a continuous, always-improving process, and it just so happens that we have a brand-spanking-new Blocktool Super Deluxe...and this one really is super. It has ten offsets instead of the normal seven. Isn't it special?! Anyway, the base template for a new BTSD block is this:


db $42


JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH : JMP MarioCape : JMP MarioFireBall : JMP TopCorner : JMP HeadInside : JMP BodyInside


MarioAbove:

MarioBelow:

MarioSide:

SpriteV:

SpriteH:

MarioCape:

MarioFireBall:

TopCorner:

HeadInside:

BodyInside:

RTL


See, the original seven offsets are there, but there are ALSO...*drum roll*...offsets for when the player is touching a top corner of the block, when the player's head is inside the block, and when the player's body is inside it. But noticed something else, too: there's a “db $42” at the top of the code. This just marks the block as having the new offsets. If there is no db $42, it will just act like the old seven-offset blocks. Fair warning, though: if you put the db $42 there, make sure you actually have the full 10 offsets, or you'll probably get crashy-crashy. Similarly, if you have 10 offsets, leaving out the db $42 might just cause you some problems. Why is it 42? Because...oh, I was so, SO tempted to make a joke about the answer to life, the universe, and everything here (tell me you didn't see that coming), but I'll spare you this time. I don't know. smkdan probably just chose that number arbitrarily.


pL1.3

There are also a couple of subroutines that come in handy when making blocks. First of all, the following code will make a block shatter, like the turn blocks do when you spin-jump them.


PHB

LDA #$02

PHA

PLB

LDA #$00

JSL $028663

PLB


Don't worry about what the PHB, PHA, and PLB mean; the important thing is the JSL $028663 and the LDA #$00 before it. If you want the block to shatter normally like the turn blocks do, use LDA #$00. If you want a multicolored shatter, like what happens when you flick a throw block at a wall and it shatters, use LDA #$01. Another useful subroutine for blocks is $00BEB0. The following code, for example:


LDA #$02

STA $9C

JSL $00BEB0


will change the current block into a blank tile. The only thing you really have to worry about here is the value after the LDA...it is not, clearly, the Map16 tile number. At $00BFC9 in all.log, there is a list of which values correspond to which tiles. Some of the more important ones are 02 (blank tile), 03 (vine), 06 (coin), 0A (multiple-coin turn block), 0B (multiple-coin question-mark block), 0C (turn block), 0D (brown used block), 0E (note block), 13 (on/off block), 14 (left side of pipe), and 15 (right side of pipe). 02 and 0D are probably the ones you'll be using the most. Now, what if you want to generate a tile that isn't in the list, like a cement block? Don't worry, there is a way. It's not nearly as quick, unfortunately, but it works. You can even generate a tile number relative to the current tile, such as the next Map16 tile, whatever it may be. I won't put the entire routine here because it is WAY too long, but I have included it in Appendix 2. Anyway, on to the next lesson.