Tutorial: cutting, pasting chr/bin strips together with ca65

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Tutorial: cutting, pasting chr/bin strips together with ca65

Post by FrankenGraphics »

This tutorial answers how to slice and merge binary NES assets, using the cc65 suite.

So the example is kind of redundant for all you seasoned programmers since you can achieve the same result with one line in bash or PowerShell (probably).

I found it useful to make this little "ca65 script" to be able to quickly pick and merge strips of tile data into one chr-rom file.

In the example, it takes most rows of tiles from dummy0.chr and the 3 last rows of dummy1.chr and concatenate them into one 4kB binary. This was used to copy common tiles (an alphabet + some HUD symbols) across level tilesheets.

ca65 has a very versatile .incbin directive. it lets you set offset and length. This means you can grab a portion of any binary. This is pretty useful for tiles especially.

For me, it circumvened having to use yy-chr to do the job, and since you can't copypaste between several NESST instances (each has its own clipboard space for tile data), this was the quickest way for me. Now i've got the script for every time i need to bake a new level tileset specific to this project.

Baby steps to make the example work:
1) install cc65 suite somewhere if you haven't
2) You need to rename the path:s in the .bat file to fit your environment.
3) optional: in merger.s, replace dummy0.chr and dummy1.chr with the files you want to merge
4) run merger.bat

It will replace and produce a new tileset called merged.chr

For any practical use of the example files specific to your project, you can:
al) adjust the offsets and lengths to taste. Remember to multiply by 16 or $10 if you're counting tiles, rather than bytes
b) add in as many or as few .incbin directives as you need.
c) change the expected size of the output in the .cfg file by changing "size = $1000" (4kB:s) to something else.
d) replace my magic numbers with some defined constants that make sense to you.

Mostly, i'm just hoping this'll raise some awareness that you can use .incbin more flexibly in any project. It can for example nondestructively pick and choose subsets of assets everytime you build your program, or sometimes just simply circumvene the need for external tools or repeated command line tasks.
Attachments
merger_example.zip
(1.1 KiB) Downloaded 112 times
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: Tutorial: cutting, pasting chr/bin strips together with

Post by Banshaku »

Yes, this option is useful and if your set flags even better. You could set a flag to slice specific files when in debug mode, test mode, release etc. With those flags passed on the command line to your make file, you could create many variation of assets for testing this way.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Tutorial: cutting, pasting chr/bin strips together with

Post by rainwarrior »

Waaaaat how did I miss this??

Ha ha, how many times I've wished .incbin had exactly that, and apparently it did all along?

(Since 2001, anyway, long before I ever used it.)

I usually just write quick python scripts to cut up ROMs though, example:

Code: Select all

rom = open("smb.nes","rb").read()
open("0.prg","wb").write(rom[16+0x0000:16+0x4000])
open("1.prg","wb").write(rom[16+0x4000:16+0x8000])
open("0.chr","wb").write(rom[16+0x8000:16+0xA000])
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Tutorial: cutting, pasting chr/bin strips together with

Post by FrankenGraphics »

FrankenGraphics wrote:Mostly, i'm just hoping this'll raise some awareness that you can use .incbin more flexibly in any project.
rainwarrior wrote:Waaaaat
Mission accomplished! :D I figured after a search that this might not be well known. Easy to miss
nice features when the sum of them are so extensive.

---

Another good thing is that you can always be sure that you're not breaking the ROM budget with a file that has been mistakenly padded. A recurring mistake i do is, when using NESST > all > save is that it defaults and pads the tilemap size to 8kB:s, rather than 4kB:s, which is the expected size in my workflow.

Doing full tilemap inclusions like so:
.incbin "name.chr",0,$1000
makes similar situations failsafe / human error less likely.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Tutorial: cutting, pasting chr/bin strips together with

Post by rainwarrior »

A place where I've wanted this was when preparing patches for existing games. Say I found 32 bytes of space at $D840, I could do something like this:

Code: Select all

.segment "prg_8000"
.incbin "smb.nes", 16, $D840 - $8000

; patch goes here

.segment "prg_D860"
.incbin "smb.nes", 16 + $D860 - $8000, $10000 - $D860
In the past, I'd instead split the ROM up into separate files to go around the patch space.

Not really that much extra work, but it's yet another step that had to be done with yet another tool, rather than just the cc65 build.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Tutorial: cutting, pasting chr/bin strips together with

Post by tokumaru »

Yeah, I too was very glad to discover this a while back.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Tutorial: cutting, pasting chr/bin strips together with

Post by tepples »

My mapper hack of Solar Wars from CNROM to UNROM uses this overlay technique. (The Action 53 volume 2 builder couldn't handle CNROM yet; that was added for volumes 3 and 4.)
Post Reply