M68000 assemblers with patching functionality?

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
Post Reply
User avatar
Sverker
Posts: 46
Joined: Wed May 23, 2012 11:30 pm

M68000 assemblers with patching functionality?

Post by Sverker »

Are there any M68k assemblers out there that allow for patching of a ROM using "org" like what currently exists for SNES? I have done some searching and cannot find anything like this. Trying my hand at a SFII: Champion Edition hack for CPS1 and it would be way easier to do it this way than manually transcribe my new code into hex. Thanks.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: M68000 assemblers with patching functionality?

Post by nocash »

ORG does normally tell the assembler to assemble the following instructions as if they located at a given memory address. It doesn't actually take care of moving data to that address, and least mixing it with an existing binary.
What you are looking for might be something like "INCBIN filename,fileoffset,length". You could also make a macro for it, where you specify only the end address in memory, and let the macro load data up to that address, with automatically computed fileoffset and length values.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: M68000 assemblers with patching functionality?

Post by koitsu »

I'm not 68K-savvy, but I'm not aware of anything like this "for the SNES" with one exception: byuu's bass. I literally haven't seen such a feature in any other assembler in my entire life.

Normally what you're expected to do is disassemble existing code, do the modifications, and reassemble it. For stuff unrelated to the disassembled portion, it's easiest to incbin (or whatever the equivalent is in the assembler) those portions, making sure they "properly line up" (address-wise). It's up to you to make sure things work properly (ex. if code in the incbin'd section does something like jmp {some-address-in-the-disassembled-portion}, and you've moved where that code actually is due to your changes, you've now created quite a bad bug).
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: M68000 assemblers with patching functionality?

Post by tokumaru »

nocash wrote:ORG does normally tell the assembler to assemble the following instructions as if they located at a given memory address. It doesn't actually take care of moving data to that address, and least mixing it with an existing binary.
Normally, the first ORG just sets the address, but subsequent ORGs will pad until the specified addresses.
What you are looking for might be something like "INCBIN filename,fileoffset,length". You could also make a macro for it, where you specify only the end address in memory, and let the macro load data up to that address, with automatically computed fileoffset and length values.
There are assemblers that allow overlapping though, but I'm not familiar with 68000 tools.
User avatar
Sverker
Posts: 46
Joined: Wed May 23, 2012 11:30 pm

Re: M68000 assemblers with patching functionality?

Post by Sverker »

Ah ok. It was some variant of xkas that I was using. Didn't realize this wasn't a standard feature. Doing a full disassembly is kinda out of the question because that would probably take me ten years, so I guess I'll do this the hard way. Thanks for the info.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: M68000 assemblers with patching functionality?

Post by tepples »

Sverker wrote:Ah ok. It was some variant of xkas that I was using.
And bass is the follow-up to xkas.

rgblink in RGBDS (Game Boy assembler) also supports an overlay file, used to fill regions where nothing got assembled.
Doing a full disassembly is kinda out of the question because that would probably take me ten years, so I guess I'll do this the hard way. Thanks for the info.
The other way is what I did with my mapper hack of Solar Wars: hack something up with offset and length arguments to .incbin.
User avatar
Sverker
Posts: 46
Joined: Wed May 23, 2012 11:30 pm

Re: M68000 assemblers with patching functionality?

Post by Sverker »

I'm thinking now I might just rig up a quick and dirty console app to keep track of everything for me on this specific project. Maybe not the most elegant solution but what can you do.
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: M68000 assemblers with patching functionality?

Post by Oziphantom »

This isn't anything amazing in terms of assembler, any half decent more than 2 pass assembler should do it. The complication you will have with 68K assemblers is they are very much from the linker era, so you might have to get the linker to do the dirty work. But any assembler that has *= for code starting should do what you want. I would just try assemblers to see. Easy68K or sn68k would be my first port of call.

If they really won't do it, you could use TASS64 as a preprocessor.

Assemble your code to a bin file. then you can just do

*=$000000
.binary "yourbinaryhere.bin"

*=$XXXX
.binary "patch.bin"
*=$YYYYY
.binary "patch2.bin"

etc
you will want to set TASS64 to binary output and 65816 mode so you get the full 16MB address space, assuming your bin file is less than 16MB.
64tass -a -x -b -f
if you need to put it to ROM the --s-record format might be useful to you as that is the Motorola S-record used by burners and downloaders.

PS if you want this for SNES 64tass has full 65816 support and if you want it for NES full N6502 support as well.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: M68000 assemblers with patching functionality?

Post by rainwarrior »

koitsu wrote:I'm not 68K-savvy, but I'm not aware of anything like this "for the SNES" with one exception: byuu's bass. I literally haven't seen such a feature in any other assembler in my entire life.
I recently learned that cc65 has an overwrite feature for this purpose. (Doesn't help OP of course.)
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: M68000 assemblers with patching functionality?

Post by nocash »

tokumaru wrote:Normally, the first ORG just sets the address, but subsequent ORGs will pad until the specified addresses.
Yeah, I`ve also seen source files for some assemblers using "ORG address" or "*=address" for automatic padding. I don't know if that's actually the widespread normal case, or a misconception, or both ; )

For padding to address, I would use things like DUP, FILL, DEFS, REPT, with "address-$" or "address-*" as length. Being able to use ORG for padding might seem useful at first glance, but that automated padding does screw up ability to relocate code manually.

For example, for a NES game, if you relocate code from ROM to RAM, you'd have "ORG 8000h" (rom) containing your relocation function, followed by "ORG 200h" (ram) containing the relocated code, plus "ORG reloc_src+reloc_len" to resume ROM addressing for further ROM code & exception vectors. How would that work on assemblers that apply padding on ORG?
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: M68000 assemblers with patching functionality?

Post by Oziphantom »

that sounds like a crazy system, if ORG sets the address of assembly, what set the PC address?

you have

Code: Select all

*=$8000 ; this set the assembly address to 8000
to change the final target of the assembly, so code that you copy and execute somewhere else you change the assembly PC but not the current PC
.logical $200
start
lda Start+5
sta $d020
rts
.byte 00
.here
so Start+5 = $205 however the code will be stored at $8000 in the output file.

To make a standard NES ROM starting at $8000 bin file you would do

Code: Select all

*=$0000 ; assembly set to output $0
.logical $8000 ; assemble as if the code is at $8000
..your code here
.here
if you have multiple banks at $8000 and a fixed bank at $c000 store in ram as 16K 8K 8K 8K overlay

Code: Select all

*=$0000
.logical $8000
16K of code here
.here
;Bank1 ; $4000 @$8000
.logical $8000
upto 8K here
.align $c000
.here
;Bank 2 ; $6000 @$8000
.logical $8000
upto 8K here
.align $c000
.here
;Bank 3 ; $8000 @$8000
.logical $8000
upto 8K here
.align $c000
.here
However I would recommend using sections and collecting them to form your actual code.

You then have the .virtual case which lets you put a struct or anything else that doesn't actually modify memory at a fixed location. For example you might want to map PPU registers this way.

Code: Select all

.virtual $2000
.block PPU
 CTRL .byte ?
 MASK .byte ?
 STATUS .byte ?
 OAMADDR .byte ?
 OAMDATA .byte ?
 PPUSCROLL .byte ?
 PPUADDR .byte ?
 PPUDATA .byte ?
 OAMDMA .byte ?
.bend
.endv
this way you don't have to actually move the assemble address or logical address and can just place a virtual move so it won't appear in the output memory map. However you can do
STA PPU.MASK and it will put $2001 for you.
The true power of Virtual is it will take an expression so

Code: Select all

.virtual #1,s
p1  .addr ?
tmp .byte ?
.endv
lda (p1),y will assemble to lda ($01,s),y
lda (tmp) will assemble to lda $03,s
Post Reply