News:

11 March 2016 - Forum Rules

Main Menu

65816 ASM change in Desktop application.

Started by Madsiur, April 23, 2016, 10:54:22 AM

Previous topic - Next topic

Madsiur

I'm currently coding an editor that move and expand some FF6 data. Right now I declare a few bytes arrays with the ASM changes, then edit the needed bytes when the user select his bank/offset the apply to ROM. However now I'm at a point where ASM changes while not being really deep are lengthy in term of bytes. I'm also opening the door to free SRAM byte(s) selection so it means more edits to the ASM code.

There's also the fact that each time I modify the code in testing phase, I got to edit multiple setByte(s) functions because everything in the array is shifted. That is just painful. I'm aware though all tests should be done on the ASM code before integrating it in the application.

What would be the ideal solution to implement ASM modifications with an editor? Should I implement like rudimentary assembler language and "embed" (dunno the english term) a asm file within my application or is there other ways to approach this? Either way I need to be able to make LDA and STA offsets changes (in raw hex) so I'll end up with numerous setByte(s) functions I think.

Disch

#1
QuoteWhat would be the ideal solution to implement ASM modifications with an editor?

1) Bundle an assembler with your editor
2) include various .asm files in a subdirectory that you distribute with your editor
3) In the editor, have an "asm hacks" sub-window that consists of just a single check-list or list of checkboxes
4) Have the editor dynamically populate that checklist by iterating the subdirectory, and add a single checkbox for each .asm file in the directory
5) When you save the ROM, invoke the assembler for each selected asm file

Madsiur

Your solution seems to be one with a lot less head scratching. I'll go for that. Thanks!

jonk

#3
Quote from: Madsiur on April 23, 2016, 10:54:22 AM
I'm currently coding an editor that move and expand some FF6 data. Right now I declare a few bytes arrays with the ASM changes, then edit the needed bytes when the user select his bank/offset the apply to ROM. However now I'm at a point where ASM changes while not being really deep are lengthy in term of bytes. I'm also opening the door to free SRAM byte(s) selection so it means more edits to the ASM code.

There's also the fact that each time I modify the code in testing phase, I got to edit multiple setByte(s) functions because everything in the array is shifted. That is just painful. I'm aware though all tests should be done on the ASM code before integrating it in the application.

What would be the ideal solution to implement ASM modifications with an editor? Should I implement like rudimentary assembler language and "embed" (dunno the english term) a asm file within my application or is there other ways to approach this? Either way I need to be able to make LDA and STA offsets changes (in raw hex) so I'll end up with numerous setByte(s) functions I think.

I've implemented one possible solution for my son, lately. I used the Merlin32 assembler/linker toolset and modifed Olivier's source code to support PC-relative branching across multiple modules (link-time support vs the prior assembly-time only support it earlier had.) [I'm in discussions right now with Olivier, who only just returned today from a long vacation in Europe, about including my modifications with his source code.) I also created a specialized patching program that can support a variety of ROM formats, accept the generated binary file fragments from Merlin32, and then properly patch code and data (tables, for example) that the assembler/linker tool generates. All this is done as a single step. So all I do is type "patch rom" at the DOS prompt and a nifty process takes place that incorporates all of the assembly source files, generating binary segments used to patch the rom, and then patching it appropriately. The result can be run in a simulator immediately.

My son is re-writing lots of code and adding many data tables. He had been hand-coding everything -- tables and code, alike. And then using Lua to patch the ROM. He would make coding mistakes, sometimes, which cost time. He would have to re-code both data and code every time he moved things around, too, costing still more time (lots of it.) So I'm moving him off of that process and into using the assembler tools to do the detailed work for him.

If you are interested, I can help with getting that to work for you.

May 04, 2016, 01:40:26 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

Here is a link to a new page I wrote on the topic I mentioned before: Patching SNES ROMs Directly from Assembly. I've been allowed to distribute my modified binary for Merlin32. That page shows how to make a small patch to an SNES ROM using the tool and includes all of the necessary source code to add additional information to the English-patched DQIII ROM for the SNES.
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me

DougRPG

Try to use the assembler Bass v14 (the last implemented by Byuu): http://byuu.org/tool/bass/

Probably you can solve this array shifiting with it.


jonk

#5
Quote from: DougRPG on May 14, 2016, 11:21:25 AM
Try to use the assembler Bass v14 (the last implemented by Byuu): http://byuu.org/tool/bass/

Probably you can solve this array shifiting with it.
I'll have a look. Thanks! I had been to byuu's page regarding higan. But hadn't looked at bass. Sounds good.

Meanwhile, I have modified Merlin32 sufficiently (I hate its expression syntax) so that it likely does similar work for me now. I've completely revamped my page on the topic and it provides a complete patching example for modifying DQ3 (with translation patch) to add X and Y field and town positions to the existing info display. It's very easy to do with the modified assembler tool, which also includes its own linker. It supports multiple modules (externals and the like) as well as single modules.

I'll see about doing exactly the same test using bass and see how that works out. Thanks for the clue!!

May 14, 2016, 04:22:58 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

Update: I'm a lot less sure now about bass. (It does include the necessary files, snes-cpu.arch and snes-smp.arch, for what appears to be necessary for SNES CPU usage. I assume these will be sufficient, for now. But while it seems extremely powerful. And I'm growing to learn more, just how much byuu has invested his life so heavily here. It is also very .... different in syntax, of course. That's the nature of something like this. It also really needs a great deal of additional documentation for use, generally.) But the main problem I see right now is how to get it to modify existing ROM formats, which are not mapped entirely in a straight binary format. So I'm holding back an opinion about whether or not this will work until I get a change to learn more.

May 14, 2016, 04:28:32 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

Update 2: There is another thing. The modified Merlin32 assembler/linker can handle assembling code to exist at one SNES address space while at the same time putting that code into a completely different ROM address. ROMs, plus mappers, can "map in" code into SNES address spaces, at will. So you might have lots of different code segments, all assembled for use at the same bank and the same addresses within that bank, yet need them placed into different places in the ROM. I have NO CLUE, right now, how to even begin to find out how to achieve that with byuu's bass. It looks to me, right now, that you can't do it, at all. The modified Merlin32 can even be set up to mirror a code/data segment into separate ROM segments, as well. It's quite general, in this regard. And it isn't tied to any one ROM format, either. The ROM format specification is itself quite general and supports not only the oddball A15 (or not) characteristic of the SNES but many other oddball hardware address mappings. I can literally write code for a complete 128Mb ROM using this modified Merlin32 tool and have it properly assemble the instructions at the correct execution time addresses while mapping them correctly onto the binary ROM file. All this despite the fact that the SNES address space is 16Mb (24 bits), but typically limited in practice to 4Mb and 8Mb ROM sizes. (I may get back to byuu's bass, when I get some more time. But for right now, without a plan of attack regarding this issue, I'm going to have to wait until I have some serious time to invest here. And given byuu's heavy and long investment, plus his personal, mental struggles circa 2014, I'm not wanting to ask him for help without having first plowed a fair bit of my own time into it beforehand [assuming he'd even reply.])

May 14, 2016, 04:42:38 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

Quote from: DougRPG on May 14, 2016, 11:21:25 AM
Try to use the assembler Bass v14 (the last implemented by Byuu): http://byuu.org/tool/bass/
So, have you used it? Are you willing to discuss how to get it to address a few questions I have?
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me

DougRPG

#6
Sorry, but I didn't understand what you are trying to do. Could you write in a single phrase what the problem is?
The main use of bass is as a patcher assembler, so you can perfectly use it to change a Rom you have.

Anyway, Snes has mainly two types of Rom, LoRom and HiRom. You first need to find what type of Rom you have, and after that create a "seek" function to adjust the "origin" and "base" variables, so the assembler can change the correct place in the rom.

For example, if you want to use and address in the Snes space, for HiRom you'll probably want to create this macro:

macro seek(offset) {
      origin {offset}
      base 0x0
}

For LoRom (using the 0x800000 region), something like that:

macro seek(offset) {
      origin ({offset} & 0x7fff) + ((({offset}-0x800000) & 0xff0000) / 2)
      base {offset}
}

This way in your assembly file you do something like:

seek(0x801234) //for LoRom

or

seek(0xc01234) //for HiRom

and after that you put the code you want, and the assembler will know the corret position inside the Rom where to put the code and the assembled code will have the correct addresses.

If you want to use an absolute Rom address, for HiRom you'll need something like that:

macro seekRom(offset) {
      origin {offset} & 0x3fffff
      base 0xc00000 | {offset}
}

and for LoRom:

macro seekRom(offset) {
      origin {offset}
      base 0x800000 + ( ( ( {offset} << 1 ) & 0xff0000) + ( {offset} & 0x7fff ) + 0x8000 )
}

So, in a Hirom game, if you do "seek(0x1234)" the assembler you know that you are putting the code at 0xc01234, for example.

You will always need to set these origin and base variables for any hack you do. Some assemblers have a different way, but the theory is the same. The assembler cannot knows how the game works, so you need to verify yourself and configure the assembler to generate to code correctly. Bass is flexible, but you need to know the theory. Probably it's not recommended for the newcommers, because it suppose you have some experience.

Look this page and you'll find a lot of bass examples:

http://board.byuu.org/phpbb3/viewtopic.php?f=16&t=123

jonk

Quote from: DougRPG on May 15, 2016, 02:48:25 PM
Sorry, but I didn't understand what you are trying to do. Could you write in a single phrase what the problem is?
<snip of useful information about bass>
Thanks for providing some thoughts even though you say I hadn't clearly communicated with you. If you are curious, I'm currently helping my son with an ExHiROM format (4mb original + 2mb added for the language patch, in this case.) However, I'm also considering a tool that will support generalized abstractions of ASIC and FPGA memory mapping capabilities, as well. (Not necessarily tied into specific ICs like the SPC7110, for example.) In this sense, I would like to be able to assemble five separate sets of code, all targeted for a specific placement in the SNES address space (each of them assembled to run at $C40000, for example) but where they are placed at five different ROM locations.

I also prefer the idea of being able to keep the binary ROM file mapping details out of my source code and placed elsewhere (in a linker file.) This allows me to have a single place where I control placement. But it's not necessary. Just a 'nice to have.'

I will go over your reply in more detail. Thank you again for writing it out and I do believe it will help, which is exactly what I was hoping for. (I have also bookmarked the discussion on bass you referenced, as well.)

Quote from: DougRPG on May 15, 2016, 02:48:25 PM
Probably it's not recommended for the newcommers, because it suppose you have some experience
I'm not new. I have written symbolic assemblers as well as C compilers, before. None of that means I'm informed about what is going on regarding SNES development, though. I'm ignorant there. But I do know the concepts.
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me

DougRPG

QuoteIf you are curious, I'm currently helping my son with an ExHiROM format (4mb original + 2mb added for the language patch, in this case.)

A 6MB rom (ExHirom) is the same as a 4MB normal Hirom, except that the cartridge will now use one more bus line, so you won't have the upper mirror. So you need to make sure you are not trying to access some data through an invalid mirror. Accessing data through mirrors is a very common precedure using games with 4MB or less.
To make sure what address to use you have to deeply understand how the Snes memory map works. You need to understand that when a cartridge has physically less address lines than others, these cartridges with less lines will have the rom data memory mirrored through the address space. So its very common different games to use different mirrors in the code. It doesn't matter, because when the address is put in the address bus the higher bits are discarted, because the cartridge doesn't use this higher lines, so the cartridge will access the correct position no matter the mirror you use.
But with 6MB you are using almost all lines, so you need to use the correct address space when you change the assembly, otherwise you could access the wrong rom data.
You need to understand this stuff to be able to set the assembler correctly.

QuoteIn this sense, I would like to be able to assemble five separate sets of code, all targeted for a specific placement in the SNES address space (each of them assembled to run at $C40000, for example) but where they are placed at five different ROM locations.

You have different sets of code and when they run they need to be at 0xc40000? You can only do this with a custom cartridge with a custom mapper. You could use a fpga for that, but I don't see the reason. With Snes you can have games up to 12MB, so why to use a mapper? If you need more than that you will have to use something like the MSU-1, that expand the Snes memory to 4gb.


jonk

#9
Quote from: DougRPG on May 15, 2016, 11:14:55 PM
A 6MB rom (ExHirom) is the same as a 4MB normal Hirom, except that the cartridge will now use one more bus line, so you won't have the upper mirror.
<snip>
You need to understand this stuff to be able to set the assembler correctly.
Thanks. But since I also design hardware used in embedded instrumentation, I'm already aware of these issues (and also aware of at least some of the meaning in this context, I think.) I still appreciate your patience in writing, regardless. So don't get me wrong about that.

Quote from: DougRPG on May 15, 2016, 11:14:55 PM
You have different sets of code and when they run they need to be at 0xc40000? You can only do this with a custom cartridge with a custom mapper.
Yes. Code will be paged in and out by cartridge hardware, as controlled by its software. It's not a novel concept.

Quote from: DougRPG on May 15, 2016, 11:14:55 PM
You could use a fpga for that, but I don't see the reason. With Snes you can have games up to 12MB, so why to use a mapper? If you need more than that you will have to use something like the MSU-1, that expand the Snes memory to 4gb.
One of my intents, among several, is to have an assembler that SUPPORTS mapper hardware where and as it already exists. Not to make something new. The assembler/linker/patcher toolset must support patching associated ROM files. I want the assembler and linker tool to support all of the already existing ROM cartridge hardware designs. Including all of those using mapper hardware. With ease. (It is only a minor hope that it would also support possible 'reasonable' future designs, though I honestly don't currently anticipate a need there.) I have yet to learn the details of byuu's MSU1 (though the description suggests that it can transfer blocks of ROM into SNES RAM regions.) But I do want to support ROM mapping hardware that can map sections of ROM into the SNES address space under software control and the associated ROM files that may depend on them.

Luckily, what I have currently does that well. It easily supports mapper designs I've considered. It assembles as many separate segments of code to the same SNES CPU addresses as I could hope for, placing them easily at distinct ROM file locations for later use by software during run-time execution on various mapper hardware options. (Plus of course, the existing hardware modes and behaviors of the basic SNES unit itself.) I believe this includes what is currently available on the SD2SNES, too. (I may, at some point, modify the SD2SNES by writing VHDL/Verilog w/floorplanning. But I may not, too.)

Right now, my son is working on DQ3. Nothing special there. The number of useful assembler tools is a larger set, if all I was thinking about was DQ3. But I'm not only thinking about DQ3 and I'm not only thinking about today. There is tomorrow...
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me