 |
|
 |
|
| Official Hex/ASM/Etc. Help Thread |
|
Forum Index - SMW Hacking - General SMW Hacking Help - ASM & Related Topics - Official Hex/ASM/Etc. Help Thread |
|
|
|
|
| Posted on 2009-07-15 09:43:31 AM |
Link | Quote |
|
That works perfectly! Thanks a lot, Kaijyuu!
EDIT: Another question... Is it possible to move the coin counter to a different place in the status bar just for one level? Well, of course it's possible, but how can I do that? Do I have to manually store the content of $0DBF to another place, or is there another way to do that?
|
| Last edited on 2009-07-15 09:53:58 AM by WhiteYoshiEgg. |
|
| Posted on 2009-07-15 10:23:33 AM |
Link | Quote |
|
This is from the helpful diagrams topic in the data repository forum.

Through level asm, or a sprite or something, you can manipulate what the status bar shows on the fly. If you can determine what should be in the status bar, put it there through this. Ex:
Code
LDA #$FE ;Number for a blank tile
STA $0F13 ;10s digit of coin counter overwritten
Now, for a question of my own. I want to look at what code the intro level (C5) uses that's unique to itself. Specifically, I want to know why message boxes on that level indiscriminately send you to the overworld. Not necessarily asking for an address to change for this, but how to find that address through a debugger or something.
|
|
| Posted on 2009-07-15 12:59:46 PM |
Link | Quote |
|
Well, normally it's the "display level message #1" sprite that does it, I think, but the CTRL-F9 changes that somehow, you could maybe compare before and after maybe? Alternatively, it might be related to the "replace overworld loading with intro level" ram address.
Looking through Carol's sprites didn't help at finding how to make Mario enter a level, does anyone know anything at all that could help?
|
|
| Posted on 2009-07-15 03:42:38 PM |
Link | Quote |
|
I'm having problems with this ASM, It's must redirect the standing still pose of Mario, works fine but It has a glitch, you collect coins but they will be not written in the coin counter, what's wrong?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Custom standing still pose
; By: Maxx, Pseudonym, Azure
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lorom ;\ ROM is LoRom
header ;/ and has a header
org $8DC4 ;\ Hack NMI
JSL Code ;/ routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Definitions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!Code_Location = $128000 ;| Location of the main code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Main Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org !Code_Location
Code:
LDA $7B
BNE Return
LDA $13E0
BNE Return
LDA #$03
STA $13E0
Return: RTL
|
| Last edited on 2009-07-15 03:46:42 PM by Dual Performance. |
|
| Posted on 2009-07-15 04:35:18 PM |
Link | Quote |
|
|
I'm trying to make a block that activates an endless P-switch effect when touched. Where are the RAM values that handle blue and silver P-switch activation? I can't seem to find it.
|
| Last edited on 2009-07-15 04:36:01 PM by Hailstorm. |
|
| Posted on 2009-07-15 04:48:29 PM |
Link | Quote |
|
You mean these?
Originally posted by RAM Map$7E:14AD - Blue POW Timer
$7E:14AE - Silver POW Timer
|
|
| Posted on 2009-07-15 05:08:18 PM |
Link | Quote |
|
|
Oh, those. So, I suppose there isn't anyway to get them to last endlessly...
|
|
| Posted on 2009-07-15 05:18:11 PM |
Link | Quote |
|
You could make the block set an unused RAM adress and use LevelASM to set the pow timer to a certain number if the RAM adress is set. That way, it will last forever*.
*Forever = until you reset the RAM adress.
|
|
| Posted on 2009-07-15 05:46:17 PM |
Link | Quote |
|
Originally posted by MrCheezeWell, normally it's the "display level message #1" sprite that does it, I think, but the CTRL-F9 changes that somehow, you could maybe compare before and after maybe? Alternatively, it might be related to the "replace overworld loading with intro level" ram address.
Looking through Carol's sprites didn't help at finding how to make Mario enter a level, does anyone know anything at all that could help?
That sprite simply displays a message and resets a few ram addresses. It doesn't actually handle warping you to the overworld.
Any text box, be it from hitting a message box to talking to an NPC sprite will send you to the overworld. I want to stop this.
As for your question, this could help you possibly:
Originally posted by RAM map7E:0EF7 1 byte Misc. If negative and Mario is on a level tile, Mario will enter it directly.
By "negative" I assume they mean it's a signed integer, and as such 80-FF would be negative.
|
|
| Posted on 2009-07-15 08:17:27 PM |
Link | Quote |
|
It's possible to define addresses relatively, isn't it? What I mean is, if I did something like this:
FreeRAM = $7F8200
Address1 = FreeRAM+0
Address2 = FreeRAM+1
Address3 = FreeRAM+2
Address4 = FreeRAM+3 etc.
or even:
FreeRAM = $7F8200
Table1 = FreeRAM+0
Table2 = FreeRAM+12
Table3 = FreeRAM+24
Table4 = FreeRAM+36 etc.
then that would work, right? Address1 would be defined as $7F8200, Address2 as $7F8201, Address3 as $7F8202, etc., and Table1 would be defined as $7F8200, Table2 would be defined as $7F820C, Table3 as $7F8218, etc. Right?
If those are correct, then I have to ask two add-on questions:
1) Does this work with minus as well as plus? Could I, for example, start at $7F8227 and define Address1 as Address-0, Address2 as FreeRAM-1, etc.?
2) Do the numbers after the + (or -) have to be in decimal? Would +$C or +$0C work as well as +12?
|
| Last edited on 2009-07-15 08:19:48 PM by imamelia. |
|
| Posted on 2009-07-15 08:36:52 PM |
Link | Quote |
|
I'm not sure if I understood exactly what you're asking, but if I did...
What you're describing is the very definition of a table.
With snes ASM, I've only ever seen them using the registers, like so:
I don't think you can use arbitrary numbers like #$04 to determine it directly. So you'd probably have to push a register and use it like so:
CodePHX
LDX #$04
LDA RAM_ADDRESS,x
PLX
That would loading the ram address + 4.
Now, if you want tables of tables that's beyond my expertise. I imagine it's possible though.
And for your last question, no you can't really use negative numbers as far as I know. I'm not sure why you'd want to anyway.
|
|
| Posted on 2009-07-15 10:50:35 PM |
Link | Quote |
|
Dual Performance:
I can point out two problems. The main one is that you forgot to restore the hacked code which was replaced by the JSL. The JSL overwrote this part of code:
LDA #$02
STA $420B
You must put it back in your own custom code, I'd say at the beginning.
Secondly, put a NOP after the JSL Code because the code you're hijacking is 5 bytes where as a JSL is 4 bytes, so we need to get rid of that extra byte by NOP'ing it out.
@Hailstorm: There isn't unless you use a loop ;)
LDA $14AD
CMP #$80
BNE Max
RTL
Max:
LDA #$FF
STA $14AD
RTL
I tested this and it works. There is no limit on the (blue) POW timer.
|
| Last edited on 2009-07-15 11:31:15 PM by Nesquik Bunny. |
|
| Posted on 2009-07-16 01:40:58 PM |
Link | Quote |
|
Originally posted by imameliaIt's possible to define addresses relatively, isn't it? What I mean is, if I did something like this:
FreeRAM = $7F8200
Address1 = FreeRAM+0
Address2 = FreeRAM+1
Address3 = FreeRAM+2
Address4 = FreeRAM+3 etc.
Yes, this is possible if your assembler knows how to add numbers like this. I know not whether "Address1 = FreeRAM+3" is valid in any assembler, but I have used plus + in both wla-65816 and xkas v0.12.
Originally posted by KaijyuuI'm not sure if I understood exactly what you're asking, but if I did... I don't think you can use arbitrary numbers like #$04 to determine it directly. So you'd probably have to push a register and use it like so:
CodePHX
LDX #$04
LDA RAM_ADDRESS,x
PLX
That would loading the ram address + 4.
Kaijyuu programmed the SNES to calculate RAM_ADDRESS + 4. I guess that imamelia wants the assembler to calculate RAM_ADDRESS + 4, and insert the sum into the machine code, so that the SNES does not need to do the calculation or use the X register.
When my assembler was wla-65816, I defined two direct-page locations called <header_buffer and <header_pathname. Each location holds a 24-bit long address. So I loaded the bank bytes to <header_buffer + 2 and to <header_pathname + 2:
Code ;; This code uses 16-bit accumulator.
;; Store 24-bit address of label cpio to <header_buffer.
;; Store 24-bit address of label result_name to <header_pathname.
;;
lda #cpio ;; load 16-bit cpio
sta <header_buffer ;; store it
lda #result_name ;; load 16-bit result_name
sta <header_pathname ;; store it
sep #$20 ;; 8-bit accumulator
lda #:cpio ;; load bank of cpio
sta <header_buffer + 2 ;; store it
lda #:result_name ;; load bank of result_name
sta <header_pathname + 2 ;; store it
rep #$20 ;; 16-bit accumulator
When my assembler was xkas v0.12, I defined a location called RAM_Lstate that holds eight bytes. To zero the bytes, I used addition:
Code define RAM_Lstate "$7fa002" // 8 bytes
// already have 16-bit A
lda.w #0
sta.l {RAM_Lstate} // set state to zero
sta.l {RAM_Lstate} + 2
sta.l {RAM_Lstate} + 4
sta.l {RAM_Lstate} + 6
I know that xkas v0.06 can do addition, but only in certain places, and there must be no spaces around the plus sign. I know not whether snescom can do addition.
Originally posted by imamelia1) Does this work with minus as well as plus? Could I, for example, start at $7F8227 and define Address1 as Address-0, Address2 as FreeRAM-1, etc.?
2) Do the numbers after the + (or -) have to be in decimal? Would +$C or +$0C work as well as +12?
Yes, the assemblers that do + plus can also do - minus. Also, $C or $0C would probably work, if the assembler uses $ for hexadecimal; assemblers tend to allow both decimal and hexadecimal. If the assembler uses % for binary, then %1100 or %00001100 would also work.
|
|
| Posted on 2009-07-16 05:53:24 PM |
Link | Quote |
|
Well, this is my very first attempt at ASM... and as expected it went kapoosh.
LDA $19
BEQ MoveMario
LDA $19
CMP #$01
BEQ MoveMarioSlow
LDA $19
CMP #$02
BEQ MoveMarioSlower
LDA $19
CMP #$03
BEQ MoveMarioSlowest
RTS
MoveMario:
LDA $7E
CLC
ADC #$08
STA $7E
RTS
MoveMarioSlow:
LDA $7E
CLC
ADC #$04
STA $7E
RTS
MoveMarioSlower:
LDA $7E
CLC
ADC #$03
STA $7E
RTS
MoveMarioSlowest:
LDA $7E
CLC
ADC #$02
STA $7E
RTS
It's supposed to move Mario fast if he's small, but slower if he's big/has powerup. Can someone tell me what's wrong and how to fix /improve it?
|
|
| Posted on 2009-07-16 07:05:50 PM |
Link | Quote |
|
|
Apparently, you're modifying RAM address $7E, not $7B. $7B is horizontal movement and $7D is vertical movement. Also, That code would work every frame Mario touches it, and that makes the speed rise a lot more than you'd expect... What is the version of blocktool you're using? If You use Blocktool Deluxe, you need to define the offesets in the asm file (refer to Custom Blocks for examples of that) and use RTLs instead of RTS. What are the offsets of your block? That might have something to do with it.
|
| Last edited on 2009-07-16 07:16:27 PM by scepile. |
|
| Posted on 2009-07-16 07:38:21 PM |
Link | Quote |
|
I would like to take an existing (custom) sprite and increase the number of hits it takes to kill it (essentially making an incredibly simple custom boss)
How would I go about doing this?
(This is my first venture into the magical world of ASM)
|
| Last edited on 2009-07-16 07:47:43 PM by NamelessProtagonist. |
|
| Posted on 2009-07-16 11:13:55 PM |
Link | Quote |
|
Asterisk, that's not bad for your first try at ASM. But there are a few ways you can optimise your code and there's also a bug:
When you're comparing a RAM Address with a bunch of values, you don't need to load them again.
LDA $19
BEQ MoveMario
LDA $19 ; irrelevant
CMP #$01
BEQ MoveMarioSlow
Can be
LDA $19
BEQ MoveMario
CMP #$01
BEQ MoveMarioSlow
Secondly, rather than just adding each value separately, you can use a table:
LDY $19 ; powerup -> Y
LDA $7B ; if going
BPL Left ; left ..
CLC
ADC Spd,y ; add speed
BRA StoreSpd
Left:
SEC ; subtract
SBC Spd,y
StoreSpd:
STA $7B
RTS
Spd:
db $00,$01,$02,$02
; 00 01 02 03 ($19)
When going left, the speed is negative (#$80-#$FF) and #$80 is the fastest. That's why you need to subtract the values instead of adding them when going left.
@NamelessProtagonist:
It isn't really a good idea to start modding sprites when you just started learning ASM. I suggest you start off by creating simple blocks and then move onto sprites/patches when you feel you can easily make them. But anyway, here is what you need to do:
In the INIT routine of the sprite, you set a specific # of hitpoints to any unused sprite misc. address in the sprite.
Check for Mario upward contact (if you can jump on the sprite, that is), and if it's positive, decrement that sprite misc. address by 1 (or by how much health you want it to lose per hit). Once that address is zero, kill the sprite.
Nevermind, Kaijyuu posted a much better and detailed explanation below.
|
| Last edited on 2009-07-17 12:34:07 AM by Nesquik Bunny. |
|
| Posted on 2009-07-16 11:46:55 PM |
Link | Quote |
|
@Nameless
If you want to learn ASM starting with coding sprites, I really don't suggest you start by modifying existing ones. There's a lot of code in them you likely won't understand unless it's heavily commented, and that can cause unnecessary headache.
I'd start with sprite tool's tutorials and work your way up to a working sprite.
Nevertheless, to answer your question:
Depends what kind of sprite it is. If it's something real simple that dies in one hit (like a shelless koopa), the easiest way to do so would be to cheak if it's dead at the end of it's routine, and bring it back to life if it's hitpoints (which you have newly defined) are not at 0.
Note that this would be significantly harder with something that already takes multiple hits to kill (such as a Rex) or acts weird when hit (such as a SMW goomba).
First off, let's make a new subroutine to keep things organized.
Code
START_SPRITE_CODE JSR SUB_GFX ; draw sprite gfx
JSR MY_NEW_SUBROUTINE ; this is where we jump to our new routine to determine hit points. Name it whatever you like
LDA $14C8,x ; \ if sprite status != 8...
CMP #$08 ; } ... not (killed with spin jump [4] or star[2])
BNE RETURN ; / ... return
LDA $9D ; \ if sprites locked...
BNE RETURN ; / ... return
You'll see something like this in most sprites. You need to put "JSR MY_NEW_SUBROUTINE" before the lines of code shown below it here.
JSR = Jump To Subroutine. This is a command to make the game read code from any arbitrary point in your sprite's asm file, and in fact the game.
Now, somewhere where there's blank space in your sprite's asm file you'll want to put this:
Code
MY_NEW_SUBROUTINE ;this is the label you typed before for your subroutine's name
LDA $14C8,x ;Loads your sprite's status value to the accumulator (A)
CMP #$02 ;Compares it to a possible state. #$02 is the falling off screen type of killed, like something getting hit with a shell
BEQ IS_HIT ; Branches if equal. Branch = go to. Unlike a JSR, this means we jump to another piece of code and don't come back unless we use another Branch command. Branches have a limited range of 128 bytes of code (I think...), while JSR has unlimited range.
LDA $14C8,x ; #$03 = Squished. Also, the ",x" you see is how we reference a sprite's data. x is a variable. We're adding x to 14C8 to determine which byte of ram stores this particular sprite's data.
CMP #$03
BEQ IS_HIT
LDA $14C8,x
CMP #$04 ; #$04 = Spinjumped.
BEQ IS_HIT
RTS ; ReTurn from Subroutine. Makes us leave this subroutine and go back to where we initially came from
IS_HIT ;This is the label we go to if one of the previous conditions is true
LDA #$08 ; #$08 is the sprite's state for "normal."
STA $14C8,x ; STA = STore A. This writes whatever is in A to the piece of ram that holds the sprite's state
RTS ; Return to subroutine
Your sprite is now immortal from normal death. (There's a couple more death states... check here: http://www.smwcentral.net/?p=thread&id=11960. Search for sprite status table near the end of the first post)
But what about hit points?
Near the top of the screen you'll see a routine with the first line being "dcb INIT". This is the initialization routine that runs only once on sprite creation.
NOTE: For the purposes of compatibility, I'm going to show you a method to store hitpoints that only allows 1 sprite of this type to be on the screen at once. I do not know if the custom sprite you're editing uses one of the misc sprite tables.
First, find an empty spot of RAM in the ram map. One off the top of my head: $7EC202
In the initialization routine, do this:
Code
dcb "INIT"
;Other pieces of code may be here. Do not edit
LDA #$03 ;Your sprite's total hitpoints. Place whatever you like
STA $7EC202
RTL ; RTL is like RTS, but they cannot be used interchangably. Explaining it is beyond the scope of this, so look it up if you're interested
Great. Now we have a piece of ram storing your sprite's hitpoints. But it's not used yet!
Go back to your custom routine.
Code
IS_HIT ;This is the label we go to if one of the previous conditions is true
LDA $7EC202 ; Load your sprite's hitpoints
CMP #$00 ; Compare them to 0
BEQ DEATH ; If equal, it is dead!
LDA $7EC202 ; Let's decrement the total hitpoints if it's not 0 yet
CLC ; "clear carry" The carry flag is part of the accumulator (A). This is to avoid possible bugs. Don't worry too much about it.
SBC #$01 ; "SuBtract from Carry" This subtracts the number from A.
STA $7EC202 ; Store the new hitpoint number to the RAM
LDA #$08 ; #$08 is the sprite's state for "normal."
STA $14C8,x ; STA = STore A. This writes whatever is in A to the piece of ram that holds the sprite's state
DEATH ; Branches here if it's dead, skipping the lines of code that revive it
RTS ; Return to subroutin
Ta-da. Done.
|
| Last edited on 2009-07-16 11:47:46 PM by Kaijyuu. |
|
| Posted on 2009-07-17 01:15:45 AM |
Link | Quote |
|
Wow... this is quite a bit more difficult than I thought it would be... even so, I'm not giving up yet...
The sprite I'm trying to edit is the Giant Goomba one. I'm trying to make the Red Goomba and Blue Goomba from Paper Mario... The Blue one would take two hits to kill and the red one three. They would be fought together (I suppose I would have to use different empty RAM addresses for each one...)
Somehow Mario passes right through the sprite, takes damage, and nothing happens to it.
Also, if I throw a shell at him it hits him several times, giving a couple extra lives, but not killing it.
I think I'm going to restart... probably going to try to read some of the original code first incase something there conflicts with what I added...
Edit: Well, I redid it and this time he still dies in one hit for some reason, and the thing that happened when I toss a shell at it still happens. Still playing around with it...
|
| Last edited on 2009-07-17 08:32:32 AM by NamelessProtagonist. |
|
| Posted on 2009-07-17 09:33:50 AM |
Link | Quote |
|
|
Upload your .asm on the file bin and I'll look at it.
|
| Last edited on 2009-07-17 09:41:13 AM by Kaijyuu. |
|
|
|
|
|
|
Forum Index - SMW Hacking - General SMW Hacking Help - ASM & Related Topics - Official Hex/ASM/Etc. Help Thread |
|
|
 |
|
 |
The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.
Copyright © 2005 - 2013 - SMW Central Legal Information - Link To UsTotal queries: 27
|
|
|
|