News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Disch

Pages: [1] 2 3 4 5 6 ... 60
ROM Hacking Discussion / Re: Hex Editing and FFHackster
« on: October 04, 2018, 12:44:17 pm »
Yeah I realize my suggestion is a lot to bite off.  Which is probably why not many people do it.  Sigh.  Maybe one of these days I'll get around to making that program.


Would it be unrealistic to go this route? Use FFHackster to edit whatever it can do naturally, and then start editing the hex to implement all of those bug fixes/updates while making many separate copies in case something breaks?

That would probably be fine, but would be a lot of work.

If you want a VERY simple build script, you really only need to learn how to do two things:

1)  Copy a file via a command line
2)  Apply an IPS patch via a command line

I'm sure there's a patcher somewhere that has a CMD interface.  LIPS might, but I'm not sure, I'm too lazy to check.

Your build script would just be a batch file that does the copy, then applies all the patches.  You're not really writing any code, just a few commands to automate.


Code: [Select]
copy /B hackster_rom.nes  my_hack.nes
ips patch1.ips my_hack.nes
ips patch2.ips my_hack.nes


The first line does a [binary] file copy, taking the file hackster is messing with and copying it to a new ROM, and then the remaining lines are applying individual patches to that ROM in whatever order you want (so these might be the hacks from that gamefaqs page, but in IPS form).  Put this in a text file with a normal text editor like notepad or notepad++, then change the extension to .bat so you can run it... and then just double-click it when you want to do a new "build".

Note, of course, that you'll probably want to change the filenames in this file.  Also, the lines for applying an IPS will probably look different depending on what patcher you're using.  Like I said I'm too lazy to find one that has a commandline interface, or what the actual command would look like, but it's probably something very similar to what I have there.

ROM Hacking Discussion / Re: Hex Editing and FFHackster
« on: October 04, 2018, 12:03:05 am »
The short answer

I wouldn't rely on it.  The quick and dirty and reasonably safe way to do this is to use FFHackster on an unedited ROM, then make a COPY of that ROM to apply those other patches to.

Do not trust FFHackster to handle a ROM with external changes.  It might work just fine if you're careful, but it's asking for trouble -- and Hackster will have no hesitation about clobbering things it doesn't know anything about.

The much, much longer answer that is really more about how people should be approaching ROM hacking in general

If this is just a quick hack that you are slapping together in a few days/weeks, then you can probably avoid this and stick to my short answer.  But if this is a serious long-term project, I highly recommend considering my advice below:

I cannot overstate this enough.... you NEED a build environment.  Each individual change that you want to make should be separated as much as possible (or as much as is reasonable) and stored in separate files.  Preferably human readable text files that allow for comments so you can know wtf that change does 3 weeks down the road.  Though in some cases you'll probably be stuck with IPS patches.

Then you need a build script that you can run, which takes ALL of those changes, applies them to a fresh, untouched ROM (in an order that you can configure and customize) -- and generates your final hacked ROM.

This provides numerous benefits:

  • VERSION CONTROL.  You can throw your project up on git. You'll never lose progress, you'll be able to make branches to experiment with new things without worrying about trashing all the work you've done, etc.  All that great version control stuff that is criminially absent from most approaches to retro rom hacking
  • You can cherry pick/remove individual changes if they cause a problem down the road merely by deleting (or commenting out or disabling) an individual file, rather than going back into your hacked ROM and "undoing" the hack
  • ROM/Project destroying conflicts can't happen anymore because there's no ROM to destroy.
  • Other conflicts can still happen but they can be minimized by isoliting individual changes.  Which makes conflicts much easier to find and fix.
  • This makes it MUCH easier to work in a group.  Seriously, trying to have multiple people editing the exact same version of a ROM is a nightmare.  But having people contributing changes to a git repo is done millions of times a day without problems.
  • I can go on all day with reasons.  Seriously... this is the way to do it

You probably should never be saving your changes directly to the ROM.  That makes them very hard to track, and makes it very easy to forget what you've done, and it makes it really hard to rewind to an earlier version if when something goes wrong.  And... frankly... it makes things harder to edit.  Editing a binary is much harder than editing a text file.

Unfortunately.... I made FFHackster like 20 years ago when "in-place" editing was kind of the norm.  But you can jump through some hoops to work around it.

  • As mentioned in the short answer, Hackster should only touch its own copy of the ROM.
  • Make some kind of script/shortcut to generate an IPS from the ROM Hackster is modifying
  • Run that script after you save changes in Hackster
  • Add a line in your build script (the one that actually will produce your hacked ROM file) to apply that IPS to the target ROM.  This should probably be the first change it applies, and you should layer other changes on top of it

You can probably even merge those last three steps to create an IPS, and apply it in the build script.  Or -- I guess skip the IPS entirely and just apply your changes to the Hackster-modified ROM (after copying it somewhere else, of course).

This adds an extra step of having to run a script after you save changes in Hackster, but that's as easy as two clicks of a mouse, or two key taps on a keyboard once you get things set up right.

FWIW -- I've kicked around the idea of making such a build tool that would allow people to approach retro ROM hacking more like modern software development but I don't really have much free time these days so I'll probably never get around to it.  :(

Newcomer's Board / Re: Is music hacking Mega Man 3 possible?
« on: September 25, 2018, 02:13:45 pm »
0)  Holy moly avoid changing the default text color/font when posting on forums.

1)  Yes, it's possible.  In general if the question is "is this possible" the answer is always "yes" unless you are trying to do something that exceeds the capabilities of the system you're working on.

2)  That's not typically how it's done.  NSFs are basically mini-programs that execute code, use RAM, etc.  Trying to insert an NSF into a game is like trying to take a chunk of code from one game and cram it into another.  More often than not that's going to lead to all sorts of conflicts and problems.

Usually the way this is done is you figure out how the game stores it's music data, then edit it in place.  There have been TONS of MM3 hacks that change the music, so I'm sure the music format is already documented somewhere.  I'm too lazy to check for myself, but there may be a doc on this site.

3)  You can use VRC6 but that is a fairly huge undertaking which you're probably not ready for.  It would involve rewriting chunks of the game code to use the new mapper, as well as pretty much rewriting an entirely new music engine from scratch to use the new audio channels.

PS)  I think Megaman 3+ all use the same music engine.  So if you find a document explaining it, you should be able to edit any of them.  MM1 and MM2 use a different engine though.  But this is just from my recollection, I could be wrong.

Programming / Re: How to learn Assembly?
« on: September 25, 2018, 11:58:01 am »
Sorta.  The assembly in TIS-100 is a very stripped down version of <insert any real life assembly here>.  The whole thing it does with the 'nodes', though, is completely fictional and unlike anything you'll find in real life.

Assembly, particularly on RISC machines like many retro consoles, really is just a collection of extremely simple instructions.  The most complex [common] instruction on the NES, for instance, just subtracts two numbers.  What makes it difficult is knowing how to chain them together effectively and efficiently to do something larger.

ROM Hacking Discussion / Re: MMC3 IRQ Problem
« on: September 19, 2018, 10:55:06 am »
But sometimes I write to $2006 when manually updating specific tiles or palettes during NMI also.  Will doing this always result in the IRQ triggering a scanline early?

If you are making A12 rise, yes.  That is what "clocks" the IRQ counter.

Really, you should do all of your drawing in VBlank first, then set your screen scroll values to whatever they need to be, then set up your IRQ counter dead last, but before rendering actually starts.  This will ensure that no matter how you muck up the IRQ counter with $2006, you'll be resetting it immediately afterwards so it doesn't matter.

Programming / Re: Converting SNES and NES addresses to PC address
« on: September 18, 2018, 01:35:34 am »
I recall from another discussion that the NES has its own formats, which depends on the mapper as well.

NES Mappers have so much variety that you can't really add "nes support", you'd have to support individual mappers (though there's a lot of overlap between different mappers).  Supporting the ~8 most common mappers will get you coverage of like ~80% of the NES library, but there are a TON (read: over a hundred) of weird/obscure mappers that were only used in like one or two games.  But again -- if you're just doing address translations, there's a lot of overlap.

It's also worth noting that converting file offset to CPU address is MUCH simpler than vice versa, since it's a many-to-one relationship.

The easiest NES mappers (like #2, #7) have only one swapping mode and only one swappable region.  Mapper 7, for instance, puts a single 32K block in the $8000-FFFF region.  So converting offset to CPU address is as simple as masking out the low 15 bits and ORing with $8000:

Code: [Select]
cpu_addr = ((offset-0x10) & 0x7FFF) | 0x8000;    // minus 0x10 for the header

Mapper #2 is also pretty easy, with the very last 16K block of PRG-ROM being fixed at $C000-FFFF, and every other bank being swapped into $8000-BFFF region:
Code: [Select]
if( offset_is_in_last_16K_of_ROM )
    cpu_addr = ((offset-0x10) & 0x3FFF) | 0xC000;
    cpu_addr = ((offset-0x10) & 0x3FFF) | 0x8000;

... other mappers, though....

Mapper #1 is more complicated.  While it only has one swappable region, it has multiple swapping MODES.  Meaning MOST of the time it operates like mapper #2.  But sometimes it operates like mapper #7.  But it also might do things a weird 3rd way (which honestly I've never seen a game use it's 3rd mode so maybe you don't have to worry about it so much unless you're a perfectionist).

And technically, which mode it uses can change at runtime, but in practice no game would ever do that.  Reliably figuring out WHICH mode any game uses is probably going to be extremely difficult, and I can't think of a good way to do it.  :(

.... and that's not the worst of it.  The most common mapper, #4, not only has multiple swapping modes, but also has multiple swapping regions.  So even if you know what mode the game uses, you have to figure out which page of PRG is going to be swapped into which region.  The first 8K in the ROM might map to the $8000-9FFF range... OR it might map to the $A000-BFFF range -- and there isn't really any way to know.

So... yeah.  Doing this on the NES is going to be a nightmare.  SNES and FDS are much easier.

Also ... I recall converting FDS addresses to be easy.

Yeah FDS is pretty straight forward.  FDS disks actually have a file system, and each file it contains has a header indicating its size and where it memory it is to be loaded.  So all you really have to do is find/read that header.

Programming / Re: How to learn Assembly?
« on: September 13, 2018, 11:10:36 am »
+1 to PolishedTurd.

Assembly is easy.  It's programming fundamentals that are hard.

Programming / Re: Random number generator in x86 assembly
« on: September 10, 2018, 11:31:43 am »
pRNGs typically work on a mathematical algorithm.  The most basic might look something like this:

Code: [Select]
out = (in * A) + B
Where A and B are moderately sized prime numbers.  'out' is the generated random number (which can be later scaled down to a specific range), and 'out' is also used as 'in' for the next iteration.

(Note:  this is extraordinarily simplistic -- modern RNGs are much more complex.. there's an entire field of study dedicated to this shit.  But I'm assuming you don't need a great one)

All you need from there is an initial value for 'in' (known as the "Seed").  An easy value for the seed is the system clock at time of program launch (if available) -- or on machines where that's not possible (like NES/SNES/etc), the count of frames between power on and the first user input is sometimes used, since that's unlikely to be identical between games.

Either way, an RNG consisting of both a 'generate' function and a 'seed' function is pretty much the universal norm, and trying to make one without a separate seed function will pretty much guarantee your RNG will suck.  My advice is to have these two functions in your RNG and leave it up to the game that uses it to figure out how to seed it properly.

So.. "hunt down the timer in each game" is what I'm recommending in this case.  The NES doesn't really have any readable register that will produce something pseudo-random, so you're SOL as far as that's concerned.

As for scaling the number down, rather than looped subtraction (which can be painfully slow if the number is small), you might consider multiplying up by the scalar and then dropping the low byte(s):

Code: [Select]
out = rng_output * scalar / max_possible_rng_output_plus_one
Example: if your RNG is single byte and produces values 0-255, 'max_possible' would be 256.  And if you want a value between 0-9, 'scalar' would be 10.  Dividing by 256 here is trivial (just drop the low byte), and this ensures output that is less than the scalar:

255 * 10 / 256 = 9


Also for systems like the NES where multiplication is a little expensive and the RNG period is going to be low anyway, the RNG computation could be replaced with a 256-byte lookup table that contains the generated sequence.

ROM Hacking Discussion / Re: Double Byte Text inserting / 16bit S-JIS
« on: September 02, 2018, 11:08:32 am »
Not to be a wiseass or snob... but.... PHP?

I mean... that would work.  But why PHP over Python?  Or Perl?  Or Ruby?

Programming / Re: SNES: Trouble writing to VRAM
« on: August 23, 2018, 10:36:17 pm »

There's a legend at the very top of the document for a code that exists for every register:

Code: [Select]

Addr rw?vhfa Name


"Addr" is the address this register is mapped into the SNES memory space.
"Name" is the official and unofficial name of the register
"bits" is either 8 or 16 characters explicating the bitfields in this register.

The flags are:
||||||+--> '+' if it can be read/written at any time, '-' otherwise
|||||+---> '+' if it can be read/written at any time during force-blank
||||+----> '+' if it can be read/written at any time during H-Blank
|||+-----> '+' if it can be read/written at any time during V-Blank
||+------> Read/Write style: 'b'     => byte
||                           'h'/'l' => read/write high/low byte of a word
||                           'w'     => word read/write twice low then high
|+-------> 'w' if the register is writable for an effect
+--------> 'r' if the register is readable for a value or effect (i.e. not
            open bus).

Note it says "H-Blank" and "V-Blank" which is why a search for Sync came up empty.


Code: [Select]
2102  wl+?+- OAMADDL - OAM Address low byte

2102 is accessible via VBlank and Force Blank, HBlank is questionable/unknown, and not accessible during rendering.

Programming / Re: SNES: Trouble writing to VRAM
« on: August 20, 2018, 01:57:01 am »
FWIW Anomie's docs on this site explain this timing business.

Register overview/reference sheet (including what regs are accessible when) + a bazillion other things:
Seriously, that doc is like the all-in-one SNES handbook and if you aren't using it you probably should be.

More detail is explained here:
...but this builds on what's explained in the first doc, so check that one first.

Newcomer's Board / Re: Where does one even begin?
« on: August 10, 2018, 10:56:13 am »
I know I'll sound like a contrarian, but if OP wants to make a 16-bit console hack, then he should just start on that 16-bit console.

100% agree.

There's no need for stepping stones here.  Just dive in and learn to do it by learning to do what you want with the game you want.

Programming / Re: Problem with irq
« on: August 09, 2018, 10:03:41 pm »
You're never acknowledging the IRQ.

You need to read from $4211 in order to acknowledge it.  You are TRYING this but you are reading from the wrong bank:

Code: [Select]
$80/8034 AD 11 42    LDA $4211  [$7F:4211]   A:0000 X:38C9 Y:0738 D:0000 DB:7F S:1FEF P:envMxdIzc HC:0388 VC:000 FC:39 I:02

Note you're reading from bank 7F, not from bank 00.

FanofSMBX's plan actually is very possible and something I hadn't thought of!

It would take a chunk of asm work to make it happen, but it's definitely doable.  The biggest downside would be that all your magic and weapons would be limited to those 4 palettes, rather than the ~13 palettes they have now.  But maybe that tradeoff is more appealing than the others?  *shrug*

Definitely interesting.  Very cool idea.

ROM Hacking Discussion / Re: Final Fantasy 1 WIP - Saving Indoors
« on: May 20, 2018, 10:08:49 am »
Nice.   :thumbsup:

So... is this saving the whole call stack?  I'd imagine that'd be necessary in order for warp staircases to work properly.

Programming / Re: 16-bit Math Problems (on an 8-bit system)
« on: May 19, 2018, 02:20:11 am »
Looks good to me!  Nice work.   :thumbsup:

Programming / Re: 16-bit Math Problems (on an 8-bit system)
« on: May 16, 2018, 12:03:37 pm »
Sorry... I'm jumping into this late and only read the most recent post:

It sounds like you are over-complicating this.

If HP is one byte:

But HP isn't one byte, so this is irrelevant.  Making a special case and treating HP under 256 differently from other cases just adds more code and makes things much more complicated.  Try to treat everything as uniformly as possible.

If you have a damage/healing calculation routine that works with 2-byte values, it will ALSO work with "1-byte" values that are really 2-bytes with the high byte set to zero.  There is absolutely no reason to code two separate routines.

I don't think I can simply convert the healing to a 2 byte number. The high byte would always be 0

You can and you should.  And highbyte=0 is exactly how you should do it.


To elaborate... this is how you'd typically compare 2 two-byte values ("P" and "Q")  (high byte is +1):
Code: [Select]
LDA P+1         ; compare high bytes first
BCC Q_is_larger ; (no need to examine low bytes if these branches take, we already know which is larger)
BNE P_is_larger

LDA P           ; compare low bytes next
 ; at this point, C,Z tell you the result:
 ; Z=set if P=Q
 ; C=clear if P<Q
 ; C=set if P>=Q

If 'Q' is only one byte wide... you can start by doing the same thing, but use an immediate zero for the high byte:

Code: [Select]
LDA P+1         ; compare high bytes first
CMP #0          ;  high byte of Q is zero
  ; ...

And if you're clever, you should be able to see how to optimize that, since CMP #0 will never clear C, and won't change Z as set by LDA:

Code: [Select]
LDA P+1         ; high byte
BNE P_is_larger

LDA P           ; low byte (as above)
; ...

Also simpler logic for this would be:

Code: [Select]
amount_to_heal = strength_of_spell();
if(amount_to_heal >= caster_hp)
    amount_to_heal = caster_hp-1;      // don't kill yourself

temp = target_hp;                      // their pre-heal HP amount
target_hp += amount_to_heal;
if(target_hp > target_max_hp)
    target_hp = target_max_hp;
    amount_to_heal = target_hp - temp; // how much we actually healed

caster_hp -= amount_to_heal;

Gaming Discussion / Re: Games featuring grappling hooks
« on: May 03, 2018, 08:50:08 pm »
- makes a thread about grappling hooks in games
- doesn't mention Umihara Kawase
- mfw

Right?  It's like the definitive grappling hook game.

Though I suppose it's understandable since it didn't get a US release and is therefore rather obscure.

Gaming Discussion / Re: Games featuring grappling hooks
« on: May 03, 2018, 11:41:30 am »
Ninja Five-0 for the GBA is pretty cool.

But the best grappling hook game I've ever played (by FAR) is Umihara Kawase for the SNES.  The entire game is basically navigating a level with really slick grappling mechanics.  It takes a minute to figure it out, but man is it fun.

In fact... I dare say... if you like grapple mechanics...  Umihara Kawase is the very best by a wide margin.

I think it also had a PSX sequel, but I never played it, so I can't vouch for it.


Apparently it was a trilogy!  And the whole trilogy is available on Steam.  Crazy.  I might have to pick that up.

Newcomer's Board / Re: Please explain like I'm 5...
« on: April 29, 2018, 10:37:22 pm »
In the most simple case, text in the ROM is stored on a way where 1 byte = 1 character in the string.  So the word "hello" might occupy 5 bytes in the ROM, one for each character.

Which byte gets mapped to which character can vary depending on the game.  Table files tell the hex editor (or some other tool) which byte gets mapped to what character, so that the tool can display the text so that the user can read it without having to look at a sea of raw hex.

So the table file itself doesn't really do anything in the game, it just gives tools a way of interpretting the data in the game.  If you want to edit the text itself, you'll have to change the bytes in the ROM.  This can be done directly with a hex editor... and I would recommend making a few VERY SMALL changes with a hex editor once you find some text just so you can see how it works.

But don't get too married to a hex editor -- it probably should not be your primary tool.  They're great to see raw unfiltered data, but you almost NEVER want to do the bulk of the work in one directly.  There's a better way to go 99% of the time.

In the case of translations, using a hex editor or relative searcher can be helpful for finding the text data, but once you've found it you'll probably want to use a text extraction tool like Atlas* to dump all the text from the game (or as much as possible) into text files... edit the text files normally, the use the tool to re-insert the text back into the ROM.  Trying to edit the text directly with a hex editor (and adjust any pointers that need adjusting) would be positively dreadful.

*(I say Atlas because that's the only one I've heard of.  I'm not a translation guy so this is not my area of expertise -- there might be a better one available, but Atlas might be a good one to start with unless someone gives a better recommendation).

Pages: [1] 2 3 4 5 6 ... 60