It is currently Fri Jul 21, 2017 1:43 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 54 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Thu Mar 13, 2014 8:43 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9787
Location: Rio de Janeiro - Brazil
Bregalad wrote:
Quote:
- 512 KiB of data is awkward to manage with only 32KiB at-a-time banking and only 2 KiB of internal RAM.

I don't think it's awkward to manage

I agree. 32KB out of 512KB isn't any harder to manage than 32KB out of 256KB.

Quote:
32k banks also means less banks, so easier to manage.

Interesting point, but I don't know if I agree with this. Even though there are less banks, you have to think more carefully about how you'll organize the code/data within them, always considering how the game engine will work, in order to minimize the amount of bankswitching operations per frame and the amount of data you have to copy to RAM.

Quote:
Also the size of PRG banks has no relationship ever with RAM size.

I think lidnariq's reasoning was that since you can only have one bank mapped at any given time, you can't access data from multiple banks at the same time, and with more RAM you could copy the data from one bank, swap another bank in and you'll effectively be accessing data from 2 different banks. Again, the total ROM size is mostly irrelevant anyway, so 512KB isn't any harder to manage than 256KB. If anything, 512KB would make things easier because you'd be able to duplicate some of the data to combine it with other things in different banks.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 8:45 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18655
Location: NE Indiana, USA (NTSC)
With 256K or more you could almost organize the game as a multicart. Perhaps that's why Battletoads includes such diverse play styles.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 2:15 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5409
Location: Canada
I'm quite fond of 32k banking. I like to divide the banks by function, e.g. one for music, a few for level maps, one for CHR tiles, one for gameplay code, etc.

The only thing I find it really unsuitable for is DPCM, unless you want to duplicate your samples across all banks that may be used during playback, but I am happy to live without.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 3:42 pm 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18655
Location: NE Indiana, USA (NTSC)
How big is your game's NMI handler? If you hit a lag frame, the CPU could be in any bank while it executes.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 4:48 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9787
Location: Rio de Janeiro - Brazil
tepples wrote:
How big is your game's NMI handler? If you hit a lag frame, the CPU could be in any bank while it executes.

The NMI code present in all banks could very well be a stub, like the Reset handler, that selects the bank with the actual code and jumps to it. The only difference is that you have to remember the index of the previous bank, in order to restore it before returning from the NMI.

The good thing is that you don't even have to sacrifice any time detecting whether the NMI interrupted the frame calculations, since the 32KB banking scheme allows you to change the CPU vectors. When there is no lag, you can safely select the NMI bank (which has the NMI vector point directly to the NMI handler) before waiting for VBlank. On the other banks, the NMI vector points to the stub NMI.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 4:50 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2863
Location: Tampere, Finland
tepples wrote:
How big is your game's NMI handler? If you hit a lag frame, the CPU could be in any bank while it executes.

Who cares? Just duplicate a tiny NMI handler that saves the bank, switches in the correct bank, and jumps to the real NMI handler. Doesn't take many cycles.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 4:58 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5409
Location: Canada
Every bank has an NMI, RESET and IRQ vector, and corresponding code, obviously (though I'm not actually using IRQ for anything, it's just an RTI).

The bank switching routine is organized like a function call, it pushes the current bank number, changes banks, executes the routine from that bank, returns to finish by popping the original bank number and switching back to it before RTS to the place the banked routine was called from.

For an NMI, you can either have one true NMI routine and have all the other NMIs bankswitch to it, or simply duplicate it in each bank. For the time being, I'm duplicating it in each bank, since it's the simpler solution. The NMI itself is currently about 480 bytes of code (some is unrolled loops that could be taken in if needed). I don't really anticipate needing to save those bytes, but if I need them back, there's enough time left in vblank to include a bank switch (the NMI just does OAM DMA + 32 byte palette + 32 byte nametable, not too heavy a load).


As an aside, I really enjoy that the cc65 toolchain's separation of assembling and linking lets me assemble common code only once before linking it in all the banks that need it. (Assembling doesn't really take a significant amount of time, I just enjoy the conceptual efficiency.)


Also, the music runs in the NMI handler, but all of its code is in its own bank. This is obviously not part of the 480 bytes I just mentioned. The music routine would never run a whole frame, but I have a flag anyway to prevent a re-entrant NMI.

I actually turn the NMI once at startup, and then my game never turns it off. This lets the music continue while screen transitions are being uploaded with rendering off, etc. and as I was getting at above, there's no need to worry what bank was active when the NMI hit (lag frames or otherwise). When a bank call is made it remembers via the stack to return to the calling bank; that's all you need to do to keep it robust.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 6:41 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9787
Location: Rio de Janeiro - Brazil
Back when I learned what mappers were, I thought working with 32KB banks would be very limiting, but now I realize that's not necessarily the case.


Top
 Profile  
 
PostPosted: Thu Mar 13, 2014 7:36 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5409
Location: Canada
I think it's no more limiting than most other arrangements.

With 16k or 8k banks you have more fragmentation, wasted space that you can't fill at the edges of each smaller bank. On the other hand, you don't have to duplicate code, as you can have one bank of code read data from many banks. 8k banking is especially useful for Sunsoft style DPCM banking, if that's the kind of soundtrack you want.

With 32k banks you have the least amount of fragmentation, almost no ROM layout tetris to do, but some amount of code duplication is unavoidable. For example, in my case, the level unpacking code appears in each level data bank. DPCM duplication is another potential source of waste space, and multiple DPCM banks is probably out of the question.

So, the space tradeoff is probably a wash. DPCM is the biggest issue, in my opinion, but it depends on your soundtrack goal.


Top
 Profile  
 
PostPosted: Fri Mar 14, 2014 1:17 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2863
Location: Tampere, Finland
rainwarrior wrote:
As an aside, I really enjoy that the cc65 toolchain's separation of assembling and linking lets me assemble common code only once before linking it in all the banks that need it. (Assembling doesn't really take a significant amount of time, I just enjoy the conceptual efficiency.)

How did you do it? I thought code duplication in cc65 was only realistically possible with macros.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Fri Mar 14, 2014 6:47 am 
Offline
Formerly ~J-@D!~
User avatar

Joined: Sun Mar 12, 2006 12:36 am
Posts: 443
Location: Rive nord de Montréal
Well, if you assemble each bank separately, include the shared code in each bank but don't export its symbols, and carefully craft a linker script, it is certainly possible. These are examples from blargg.


Top
 Profile  
 
PostPosted: Fri Mar 14, 2014 8:02 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5409
Location: Canada
It's simpler than that. I just link each bank separately and combine the resulting binaries into the NES ROM. This way there's no potential conflict between symbols.

You don't need to link them together because 32k banks don't need to know about each other's symbols. The only interaction between banks is through the banked calls, which go through switching routine I described which has to be at a fixed location anyway. Similarly, all of my RAM reservations are gathered into a single object that gets linked with all of them.


You could link them all together, sure, but then you have to resolve the symbol conflicts. I did this in the past by using .scope around an .include of a shared code file, but once I realized the different banks didn't need to be linked together I abandoned this approach.


Top
 Profile  
 
PostPosted: Fri Mar 14, 2014 9:30 am 
Offline
Formerly ~J-@D!~
User avatar

Joined: Sun Mar 12, 2006 12:36 am
Posts: 443
Location: Rive nord de Montréal
Ok, so each used 32K bank is a memory region in your linker script, and you use the file attribute to link banks individually to output files and then, in the next pass, you make a NES file out of the generated binary files, with a script or another asm file that incbins each bank? Or you forget the file attribute altogether and just generate several differently named bin files? (could easily be done that way with a makefile, and indeed be even easier)


Top
 Profile  
 
PostPosted: Fri Mar 14, 2014 9:55 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5409
Location: Canada
No, I'm not using multiple output files in a single link. Each bank is its own separate link operation. They all use the same linker CFG, which looks like this, currently:
Code:
MEMORY {
   ZP:       start = $00,   size = $100,  type = rw, file = "";
   STACK:    start = $100,  size = $100,  type = rw, file = "";
   BSS:      start = $200,  size = $600,  type = rw, file = "";
   PRG:      start = $8000, size = $8000, type = ro, file = %O, fill = yes, fillval = $EA;
}

SEGMENTS {
   ZEROPAGE: load = ZP,     type = zp;
   STACK:    load = STACK,  type = bss;
   OAM:      load = BSS,    type = bss, start = $200;
   RAM:      load = BSS,    type = bss;
   ALIGNED:  load = PRG,    type = ro,  start = $8000, optional = yes;
   CODE:     load = PRG,    type = ro;
   DATA:     load = PRG,    type = ro;
   FIXED:    load = PRG,    type = ro,  start = $FE00;
   VECTORS:  load = PRG,    type = ro,  start = $FFFA;
}

I just concatenate the header and binaries after linking.

ALIGNED is a place for a couple of timing critical routines, so I can be sure they don't cross a page.

FIXED is the place for the bankswitch routine, though I have also put my common NMI routine here.


Top
 Profile  
 
PostPosted: Sat Mar 15, 2014 12:05 pm 
Offline

Joined: Mon Sep 27, 2004 2:57 pm
Posts: 1246
Couldn't you hypothetically extend AxROM to a size as big as 4 MB with an octal latch? You wouldn't even need to move the nametable select bit if you didn't want to break compatibility with smaller AxROM games.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 54 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 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