It is currently Sun Oct 22, 2017 12:31 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: Thu Sep 27, 2007 7:20 am 
Offline

Joined: Thu Jul 13, 2006 3:15 pm
Posts: 177
I've been using CA65 for almost a year now. MY first game ws NROM which was failrly easy to setup in terms of the code and linker files.

Now I am checking out UNROM. I've goten things setup and working, but it just feels like a kludge.

I was thinking I would show what I have, and let people share their opinions on a cleaner approach to organizing and assembling multiple PRG banks with CA65.

Basically here's what I did. I have 8 PRG banks (its UNROM) so I setup 8 PRG memory segments in the linker file. Then to enforce that each segment would actually be $4000 in size, I declared a start and end segment for each in the SEGMENTS section. Then in my individual .asm files (one per PRG bank) the first line declared the segment start and the last the segment end. (I also added some extra segments for the fixed PRG bank related to vectors, etc..)

Here's the linker file:

Code:
MEMORY {
  PRG0:  start = $8000, size = $4000, type = ro, file = "bank0.prg";
  PRG1:  start = $8000, size = $4000, type = ro, file = "bank1.prg";
  PRG2:  start = $8000, size = $4000, type = ro, file = "bank2.prg";
  PRG3:  start = $8000, size = $4000, type = ro, file = "bank3.prg";
  PRG4:  start = $8000, size = $4000, type = ro, file = "bank4.prg";
  PRG5:  start = $8000, size = $4000, type = ro, file = "bank5.prg";
  PRG6:  start = $8000, size = $4000, type = ro, file = "bank6.prg";

  PRG7:  start = $C000, size = $4000, type = ro, file = "bank7.prg";
}

SEGMENTS {
  BANK0:     load = PRG0, type = ro, align = $100;
  BANK0_END:     load = PRG0, type = ro, start= $C000;
  BANK1:     load = PRG1, type = ro, align = $100;
  BANK1_END:     load = PRG1, type = ro, start= $C000;
  BANK2:     load = PRG2, type = ro, align = $100;
  BANK2_END:     load = PRG2, type = ro, start= $C000;
  BANK3:     load = PRG3, type = ro, align = $100;
  BANK3_END:     load = PRG3, type = ro, start= $C000;
  BANK4:     load = PRG4, type = ro, align = $100;
  BANK4_END:     load = PRG4, type = ro, start= $C000;
  BANK5:     load = PRG5, type = ro, align = $100;
  BANK5_END:     load = PRG5, type = ro, start= $C000;
  BANK6:     load = PRG6, type = ro, align = $100;
  BANK6_END:     load = PRG6, type = ro, start= $C000;

  BANK7:     load = PRG7, type = ro, start = $C000;

  BANK_SWITCHING_TABLE:  load = PRG7, type = ro, start = $FFF0;
  VECTORS:  load = PRG7, type = ro, start = $FFFA;
}


And here is a sample (blank) ASM file corresponding to one of the banks (in this case bank 3)

Code:

.segment "BANK3"
; start of bank is at $8000


; insert code for PRG bank 3


; bank ends at $C000 (non inclusive)
.segment "BANK3_END"



And here is a sample makefile
Code:
# To build the NES ROM  just type: make
# To run the NES ROM  just type: make run (or: make fceu)
# Note: as with any make system, if any of the files have been updated they will
# be rebuilt along with any parts that are dependant on them

# Tools required. Update these to point to where they are installed
AS = C:\Personal\NES\Dev\Compilers\cc65\bin\ca65.exe
LD = C:\Personal\NES\Dev\Compilers\cc65\bin\ld65.exe
EMU1 = C:\Personal\NES\Dev\Emulators\nintendulator\nintendulator.exe
EMU2 = C:\Personal\NES\Dev\Emulators\fceu-0.98.15-rerecording\fceu.exe

MAIN = myGame

# intermediate files
HEADER_OBJS = header.o
OBJS = bank0.o  bank1.o bank2.o bank3.o bank4.o bank5.o bank6.o bank7.o


ALL_PRG = bank0.prg bank1.prg bank2.prg bank3.prg bank4.prg bank5.prg bank6.prg bank7.prg



# the part that does the compiling, assembling, linking etc..

all: $(MAIN).nes

clean:
        rm $(OBJS) $(HEADER_OBJS) $(BANK_OBJS) $(MAIN).hed $(MAIN).nes $(ALL_PRG)

nintendulator:  $(MAIN).nes
        $(EMU1) $(MAIN).nes

fceu:   $(MAIN).nes
        $(EMU2) $(MAIN).nes

run: $(MAIN).nes
        $(EMU1) $(MAIN).nes

# For making the header
$(HEADER_OBJS): %.o: %.asm
        $(AS) $(CFLAGS) $< -o $@

$(MAIN).hed: $(HEADER_OBJS)
        $(LD) $(HEADER_OBJS) -C header.ini  -o $(MAIN).hed


# For making the PRG
$(OBJS): %.o: %.asm
        $(AS) $(CFLAGS) $< -o $@


$(ALL_PRG): $(OBJS)
        $(LD) $(OBJS) -C nes.ini


# For making the final iNES ROM
$(MAIN).nes: $(ALL_PRG) $(MAIN).hed
        cat $(MAIN).hed $(ALL_PRG)  > $(MAIN).nes



So, any opinions. Am I making this an unmaintainable mess?
Should I just have separate linker files for each bank. (Thats what I did for my header file.)


EDIT - final question. How do you guys normally access addresses in your banks. What I mean is, my labels in bank1 cannot be directly accessed by the code in bank7, so I've been using constants with SEGMENTS corresponding to those address constants. Am I again making things too complicated?

Al


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group