Acmlm's Board - I2 Archive - Super Mario World hacking - Ran into another ASM wall
User | Post |
HyperLamer
Posts: 7745/8210 |
When you get a coin, the game checks if you have 100 and if so, gives you a 1up and sets the counter back to 0. I think calling $05B34A will give you a coin and handle the 1up stuff, but I've never tried it. |
Kailieann
Posts: 50/106 |
It would be helpful if information about things like the addressing modes were in, say for example, one of the stickies. Or the help file from Glyph's sticky.
Then again, most of the stickies are so bogged down with extra posts that I can't get through most of them anyways.
It works now, though I assume you'd already guessed that. Clearly incrementing the coins every frame isn't what I had in mind (like I said, the coins were only to test the rest of the code), though I find it extremely interesting that doing so can make the coin counter go past 99 all the way up to P5. I guess the whole 1-up thing doesn't actually have anything to do with the number of coins you have.
-----
Okay, anyone know of a way to check and see if a button was just pressed, rather than being held?
I tried out the following script using 7E0016 to see if I could increment the coins every time down was pressed, but nothing happened.
AD 16 00 29 04 C9 04 D0 07 AD BF 0D 1A 8D BF 0D 60
LDA $1600 ; Load 1-frame control data to accumulator AND #$04 ; Check to see if down is pressed CMP #$04 ; Set z-flag if down is pressed BNE #$07 ; Skip to end if z-flag is not set LDA $BF0D ; Load coins to accumulator INC ; Increase accumulator by 1 STA $BF0D ; Store accumulator to coins RTS ; End
Thoughts, anyone? |
BMF98567
Posts: 1204/1261 |
Whoooooooa there...you're getting some of your opcodes mixed up. It's no wonder the code isn't working right.
First example:
A5 15 EB A5 17 C2 20 CD 81 00 F0 05 A9 63 8D BF 0D 60
The snippet of code I provided wasn't complete, it was just an example (I didn't think you'd actually use it ). C2 20 puts the accumulator (A) into 16-bit mode, so it can work with two bytes at once (it can hold two regardless of what mode it's in, but you have to use XBA to swap the high and low bytes). The problem here is that you're not setting it back to 8-bit mode afterwards, so the CPU reads the following opcodes wrong and eventually crashes. You need to stick an E2 20 (SEP #$20) after the CMP to fix this. Also, you've got the wrong CMP opcode there, and your operand is reversed (00 81, not 81 00; $17 is the low byte, and $15 is the high byte, due to the XBA byte swap). CD is "CMP Absolute," which compares A to the address specified in the operand. You want C9, "CMP Immediate," which compares A to the value in the operand. You should probably read up on the different addressing modes used in 6502/65c816 ASM (Absolute, Indirect, Implied, etc.) before you go much further.
You've also got the wrong conditional branch there. F0 (BEQ) will branch if A == #$8100--this means the code is skipped when the correct buttons are pressed! Change that to a D0 (BNE), so it branches if A != #$8100.
So, the proper code would be:
A5 15 EB A5 17 C2 20 C9 00 81 E2 20 D0 05 A9 63 8D BF 0D 60
Remember, though, this particular code will work ONLY if the player is pressing nothing but A/B + Right.
Second example:
AD xx xx 35 81 C5 81 ?? 07 AD BF 0D 1A 8D BF 0D 60
Again, you're using the wrong opcodes (right function, wrong addressing mode). 35 81 should be 29 81, and C5 81 should be C9 81. ?? 07 should be D0 07 (you want to branch if A is NOT equal to #$81). The corrected code:
AD xx xx 29 81 C9 81 D0 07 AD BF 0D 1A 8D BF 0D 60
Also, keep in mind that since you're reading the "button held" flags, the coin counter is going to increment once per frame as long as the buttons are held (but maybe that's what you want?).
Overall, you're doing awesome so far. Just read up on those addressing modes like I told you, and you'll be an ASM guru in no time. |
Kailieann
Posts: 48/106 |
Okay. I've tried again, this time incrementing the coin counter so I can get a clearer picture of what's going on.
And, again, it doesn't work on the left side, and it completely ignores the B button. But at least now I know it only works while I'm holding right.
What I have now is this: AD xx xx 35 81 C5 81 ?? 07 AD BF 0D 1A 8D BF 0D 60
with xxxx being either 1500, A20D, or AA0D, and ?? being either D0 or F0 since I still can't keep my branch statements straight.
For reference:
LDA $xxxx ; Load one of the control addresses to the accumulator AND #$81 ; Checks to see if Right+B is pressed CMP #$81 ; Sets z-flag if Right+B is pressed BNE/BEQ #$07 ; Skips the next 7 instructions LDA $BF0D ; Load Coins to the accumulator INC ; Increase accumulator by 1 STA $BF0D ; Store accumulator to Coins RTS ; Exit
And blocktool offsets: Below/Above/Sides: 0 Spr UD/SprLR/Cape/Fireball/Reloc: -1
Map16 Number 512 (0x200), behavior: 130
As far as I know, this should work. But it doesn't. Can anyone see anything I'm missing? Can someone test to see if they get the same results? And can someone please find out what the hell is making it not work from the left side of the blocks, because that is just mind-boggling.
I tried putting a cement block (130) above and to the right of the blocks in question, and for some reason nothing happens when I'm right up against it, either. The only thing I can figure is that somehow block 130 (and all blocks that act like it) somehow block scripts when you're right against their left edge.
Which makes absolutely no sense, but then neither does anything else about this. |
HyperLamer
Posts: 7698/8210 |
I'm pretty sure the game was designed to be as NES-like internally as possible. If you look at the controller map, the first byte is the same as an NES's would be, and then the second distinguishes between A/B or X/Y and tells whether L and/or R are pressed.
Those 0DAx addresses are certainly interesting. If that doesn't work, it may be necessary to hack the controller routine to store more detailed information elsewhere. |
Kailieann
Posts: 41/106 |
I did actually know about $17, but since it doesn't do anything when the d-pad or the B button is pressed, I ignored it and stuck with $15 (though I did know about the A/B thing, I just overlooked it).
Incidentally, as far as I can tell, $0DA2, $0DAA, $0DA4, and $0DAC also store controller input, though DA2 and DAA don't do the A/B thing. Maybe I should try using one of them instead.
As for Blocktool, I had Above and Below set to -1, because I only wanted it to work from the sides.
At any rate, the second one you provided seems to work (now I just have to figure out how to put in the actual code I wanted..), though I'm not sure I want the option of A being in there (I'll try one of the DAx offsets later). The XBA one crashed the game for some reason. It should be A5 15 EB A5 17 C2 20 CD 81 00 F0 05 A9 63 8D BF 0D 60, yes? |
BMF98567
Posts: 1201/1261 |
OK, first off, you need to know that SMW actually uses two RAM addresses for its button flags: $15 and $17 ($16 and $18 store the same flags, but for only one frame). $17 holds the status of the L, R, A, and X buttons on the SNES controller:
The problem with SMW is that, for some reason, it doesn't differentiate between A and B + A. B = 80 00, A = 80 80, and B + A = 80 80 (normally A = 00 80). Basically, this means that unless you require the player to press NOTHING but B + Right (LDA $15, XBA, LDA $17, REP #$20, CMP #$8100), both A and B are going to trigger it.
Anyway, if you don't mind either A or B triggering the code, then it should look like so:
A5 17 29 81 C9 81 D0 05 A9 63 8D BF 0D 60
LDA $17 ; load controller flags AND #$81 ; isolate right and A/B flags CMP #$81 ; are right and A/B both pressed? BNE #$05 ; if not, branch to end LDA #$63 ; load 99 coins STA $0DBF ; store to coin counter RTS ; end
(notice I eliminated the redundant RTS by branching to the end of the routine...not required, just good form)
That SHOULD work just fine. I don't know why it would only activate on the right side of the block...did you double-check your offsets in Block Tool? (Above, Below, and Sides should all be set to zero) |
Kailieann
Posts: 39/106 |
Nope. Still only works on the right side of the block, works if I press left or right (should only be right+B), and ignores B completely. |
Sukasa
Posts: 1910/1981 |
After the AND #$81, add in a CMP #$81. That should do the trick. |
Kailieann
Posts: 36/106 |
ohhkay.... it worked... but only from the right side of the block, and not the left. And also regardless of whether or not B is pressed. |
HyperLamer
Posts: 7674/8210 |
Try AND in place of BIT. |
Kailieann
Posts: 35/106 |
Okay, this time I was trying to make a block that would respond to certain buttons being pressed.
Most of the button input is handled by 7E0015 (as some of you already know), using the following values (or combinations thereof)
01 Right 02 Left 04 Down 08 Up 10 Start 20 Select 40 Y 80 B
For my test block, I was trying to get it to respond to the combination of Right+B (81). But the problem is that I wanted it to respond to that combination regardless of any other buttons that might be pressed (seeing as I very rarely take my thumb off the Y button, myself).
So instead of CMP, I went with BIT, and got... nothing. Again, for testing, the result I was aiming for was to set Mario's coins to 99. But, of course, it didn't, because it did nothing.
So. What did I screw up this time?
AD 15 00 24 81 D0 01 60 A9 63 8D BF 0D 60
LDA $0015 ; Load 7E0015 to accumulator BIT #$81 ; AND 81, set z-flag if bits are shared BNE #$1 ; Skip 1 instruction if z-flag not set RTS ; Return LDA #$63 ; Load 63 to accumulator STA $0DBF ; Store accumulator to 7EBF0D RTS ; Return
I'll admit, I've never been good with bitwise operators, and I've still only been learning ASM for less than a week, but at least I'm trying. |
|