Points of Required Attention™
Please chime in on a proposed restructuring of the ROM hacking sections.
Views: 88,489,670
Main | FAQ | Uploader | IRC chat | Radio | Memberlist | Active users | Latest posts | Calendar | Stats | Online users | Search 04-26-24 09:03 PM
Guest: Register | Login

0 users currently in ROM Hacking | 2 guests

Main - ROM Hacking - MM1: Spawn life energy capsule after beating rematch boss New thread | New reply


Insectduel
Posted on 08-19-08 08:20 PM (rev. 5 of 08-21-08 07:51 PM) Link | Quote | ID: 89171


Hammer Brother
Level: 68

Posts: 121/1069
EXP: 2687864
Next: 40936

Since: 02-16-08
From: Insectduel's office

Last post: 1257 days
Last view: 1256 days
I've been researching and editing MM1 since March. Now it's time to share one of my ASM codes I done recently (Unless you've done it on your own). The code I done is quite a genius for me because I need to recover some health each time I defeated a rematch boss in the wily levels. If you're a newbie or an existing MM1 hacker, then this is the right time to use it.

ROM OFFSET 0x1CABA and edit the following in your favorite hex editor.

The code has been removed by the user.


Example in screenshot



OOPS! I shouldn't call it a Gutsblock. Damn you Bisqwit. It's a special object#01.

Let me tell you something newbies just in case you don't know ASM. JSR jump to a new location while saving the current program counter. This is done by pushing the program counter onto the stack, then jumping to the location. In order for the user to return from the subroutine back to the originally saved program counter, a RTS or RTL instruction must be executed.

Basically I added new codes into an empty space because I don't want to overwritten the existing code. My current ROM uses freespace mostly for enemy AI's and others for everything else. The freespace location I used is at ROM offset 0x17F86. Use this address only if you're NOT using any space. Otherwise change another JSR code in the other RAM address.

BUT, there is a major problem. This takes away the spawn teleport in Wily 4 (Sprite 43). So if you're plan to use it in your hack, you have to change another scroll about 1 right or 1 down and don't forget to add special object 01 in your scroll path.


See NetSplit's post.

NetSplit
Posted on 08-20-08 01:58 AM (rev. 2 of 08-20-08 02:18 AM) Link | Quote | ID: 89177


Level: 32

Posts: 108/178
EXP: 188038
Next: 18404

Since: 02-26-07

Last post: 2217 days
Last view: 2142 days
This is one of the assembly hacks I've done for my MM1 hacks a few years back, albeit a more complex version. However, I'm confused by your implementation, and see some syntax problems that could cause major issues. For reference, here's the original routine, with some more comments thrown in by yours truly:

0001CAAA: A5 31     lda CurrentStage
0001CAAC: C9 07 cmp #$07
0001CAAE: F0 1E beq + ; $CACE
0001CAB0: A9 01 lda #$01
0001CAB2: 85 2F sta RefObjectNumber
0001CAB4: A9 43 lda #$43 ;Spawn a teleport if it wasn't Wily2 (Teleporter ID)
0001CAB6: A2 1F ldx #$1F
0001CAB8: 20 7B F6 jsr InitActor

0001CABB: A9 08 lda #$08 ;(Teleporter x coordinate)
0001CABD: 9D 80 04 sta ObjectPosX,x

0001CAC0: A8 tay
0001CAC1: 20 33 F5 jsr InitObjectDefaultSpeed
0001CAC4: A9 B0 lda #$B0 ;(Teleporter y coordinate)
0001CAC6: 9D 00 06 sta ObjectPosY,x

; Make object invisible and collidable with Megaman
0001CAC9: A9 22 lda #$22 ;(Teleporter flags)
0001CACB: 9D 20 04 sta ObjectFlags,x
+
0001CACE: A9 00 lda #$00
0001CAD0: 85 3E sta BossCurrentStrategy

0001CAD2: A9 F8 lda #$F8 ; Disable boss
0001CAD4: 8D 01 06 sta ObjectPosY+1

0001CAD7: A2 FF ldx #$FF
0001CAD9: 9A txs
0001CADA: 4C 5E 91 jmp $915E


I don't know if Bisqwit has changed the address format to the better format your addresses are in since I last grabbed the disassembly, but the addresses here are in ROM format without a header. I'll use the addresses the code would use.

So, if you're willing to sacrifice the teleporter, then I don't see why you can't just NOP out the first 6 bytes ($CAAA-CAAF) and modify $CAB5 to #$40, $CABC to #$80, $CAC5 to #$28, and $CACA to #$13. The way you did it is confusing; you shouldn't have to be using freespace. Furthermore, just a word of warning: be careful using space in other banks. You have to know for a fact that the bank you're using is always loaded. It may be in this case; I don't know. Just keep in mind that in many cases the game can have a different bank loaded if it wants to, which would cause the JSR you have there would probably cause a crash.

Also, if you're posing modified assembly, please change all of the comments so that they're not mis-commenting (see line $CAD3). Your labels are a mess, too; for example, at $CAD5, you have a 9D opcode (STA Absolute,X) that's labeled as a STA Absolute, and the address is labeled as ObjectPosY+1, but it should be ObjectPosX,x. Your labels are all moved to the side after the address, so any assembler trying to reassemble this would choke everywhere because it would replace the labels with addresses and then have multiple addresses per instruction. You also have a JSR at the end that's way off; + is useful for branching forward or backward without declaring labels (I use an assembler that doesn't have it. Believe me, it's a great feature I wish I had). It's used for branches, while you used a JSR here. Additionally, ++ means to branch to ++, not to +\n+. Remove the ++ and just keep $BF76 and that JSR will assemble properly...oh, and make sure your comments start with a semicolon. You could also say JSR Freespace and then put a "Freespace:" label at $BF76, and that'd assemble fine, too.

There's a definite flaw here, though. Your routine does a JSR to the code at Freespace, but does a JMP out of it. The JSR puts 2 bytes onto the stack (a return address), and if the game tries to get that data back with a PLA or something to that effect, it'll get the address instead of data and will possibly crash (and almost certainly do something unsavory when it gets to the next RTS). The JSR at $CADA should be a JMP so you don't put anything on the stack, and then you also won't need the RTS at $BF83, since there's an impassable JMP right before it. Frankly, unless there's an RTS at $CADD, I'm a bit surprised this routine seems to function properly.

Anyway, sorry for the long post. I hope you learned a bit. I think it's worth being a hardass when it comes to programming code for multiple reasons. First is that it's important to practice good programming habits, which includes minding the stack. Stack abuse is something that almost always leads to problems and crashing. Another is that you have assembly code here, but it can't be assembled. There'd be errors all over the place. Typically, if an assembler can't read it, then it will be difficult for humans to read it, too, since there's some confusing element in there. I realize you were probably using this for reference and were inputting machine code directly into a hex editor, but that's not a good excuse when posting 'functional' code.

A good start, though. You found the routine and modified it to seemingly function properly, which is great. Just mind your syntax and, more importantly, your stack, and you're good to go. Also, when modifying a routine, try to figure out more about it (like where the teleporter X and Y are coming from) so you don't have to make redundant, bloated code that requires precious freespace and uses excess precious cycles.

Now that I'm done picking that apart... The item disappears after a set amount of time, right? If you want to have some more assembly fun, you could look into why and how to stop that. I implemented that that in my hack, as well, making this a special-case item (it differs from standard energy powerups in two ways, with no timer being one of them). You can disable the timer either with another assembly hack or by changing how you handle the spawning of the item; I chose the former because the latter didn't fit my implementation.

For some beginning ASM modification, decent work.

Insectduel
Posted on 08-21-08 08:27 PM (rev. 2 of 08-21-08 08:36 PM) Link | Quote | ID: 89279


Hammer Brother
Level: 68

Posts: 122/1069
EXP: 2687864
Next: 40936

Since: 02-16-08
From: Insectduel's office

Last post: 1257 days
Last view: 1256 days
Of course, I was so stupid. I haven't got the edge to see the code properly before I modify it but this is pure genius. Anyway, the code I used causes a bug after I beat wily in stage 4 causes him to fall from the top middle screen.

Sorry about the mixed, confusing writing. I was using the FCEUABS Debugger to copy a few notes down with Bisqwit's notes as well and haven't got time to find out.

I'm not sure what MM1 ROM I'm using but I used Mega man (U) [!] to edit and I'm not sure if it has a header (or a change of an iNES header) or not.

It's really fun to learn ASM on my own as I'm still learning some basics and stuff.

NetSplit
Posted on 08-22-08 12:14 AM Link | Quote | ID: 89285


Level: 32

Posts: 110/178
EXP: 188038
Next: 18404

Since: 02-26-07

Last post: 2217 days
Last view: 2142 days
Your ROM will certainly have a header. The address format used in your code is superior because the game's code never cares about the addresses in the .nes, but rather in loaded ROM. It's not always possible to figure out what that address will be just by looking at the .nes addresses. Bisqwit has that style of address for part of the document because that section is based on AlphaBeta's old Mega Man document.

Interesting that it caused Wily to fall through the floor. Using my method fixes that?

And yeah, learning assembly is great. It's all about diving right in and getting a lot of practice.

Main - ROM Hacking - MM1: Spawn life energy capsule after beating rematch boss New thread | New reply

Acmlmboard 2.1+4δ (2023-01-15)
© 2005-2023 Acmlm, blackhole89, Xkeeper et al.

Page rendered in 0.019 seconds. (341KB of memory used)
MySQL - queries: 42, rows: 65/66, time: 0.015 seconds.