It is currently Fri Nov 17, 2017 7:43 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Tue Oct 24, 2017 12:37 pm 
Offline

Joined: Tue May 09, 2017 5:03 am
Posts: 11
I feel like this should be simple, but I've been banging my head against the wall for 2 days with it.

I'm making a game using mapper 11. I only have two 32k PRG banks, one for the main game engine and the other is used to store a bunch of arrays containing 96 bytes of level data. Everything is basically working like I want it to, except I can't use memcpy to copy the array. Here is the code I have at the same address in PRG0 and PRG1

Code:
void Load_Array(void) {
   do_Switch = 1;
   while (do_Switch) {
      new_bank = PRG_bank + CHR_bank;
      change_reg(new_bank);         // Call to bank switching routine
      do_Switch = 0;               // Break the loop so we can return
   }

}

// At the same address in PRG1
void Load_Array1(void) {
   do_Switch = 1;
   while(do_Switch) {   
      new_bank = PRG_bank + CHR_bank;
      change_reg(new_bank);
      
      memcpy(L_MAP, All_Levels[level], 96);

      PRG_bank = 0x00;      // Send us back to PRG0
   }
}


If I use this, the game resets. I'm guessing that what is happening is the code for memcpy doesn't exist in PRG1, and the first code the game encounters is the reset code, which switches back to PRG0 and resets (as it should). I've tried using a for loop instead of memcpy, but I have the same problem. I can copy each byte individually, but that's it.

Code:
   // I tried a for loop, but it also doesn't work.
   for (A = 0; A < 96; ++A) {
      L_MAP[A] = All_Levels[level][A];
   }
   
   // Even this doesn't work.
   L_MAP[A] = All_Levels[level][A];

   // This works, but is disgusting.
   L_MAP[0] = All_Levels[level][0];
   ...
   L_MAP[95] = All_Levels[level][95];


Obviously this is hardly ideal, but at least it does show that I'm switching PRG banks successfully. Right now I just have extremely ugly, bloated code that I want to get rid of. I'm guessing that I'll have to write something in assembly that will copy data into my L_MAP array, but I'm having trouble wrapping my head around it for some reason.


Top
 Profile  
 
PostPosted: Tue Oct 24, 2017 1:20 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
The compiler has a set of runtime library routines that it will sometimes insert calls into. You have no control when and if such calls are made. If you turn on optimizations, there will probably be less calls (and more inlining), but you can't count on there being no calls. Thus, you must make sure that these library routines are always banked in. In your case, you have to (in whatever way) duplicate them in both of your 32 KB banks, at equivalent addresses. By default they go in the CODE segment.

Two tips: 1) Look at the assembly listing of your code, 2) Use a debugger.

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


Top
 Profile  
 
PostPosted: Tue Oct 24, 2017 1:24 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1823
Location: DIGDUG
Since memcpy is a c library function... It is likely compiling into one bank and not the other.

My Solution. Compile the 2 banks separately, concatenate them together as a final step.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Oct 24, 2017 1:53 pm 
Offline

Joined: Tue May 09, 2017 5:03 am
Posts: 11
dougeff wrote:
Since memcpy is a c library function... It is likely compiling into one bank and not the other.

My Solution. Compile the 2 banks separately, concatenate them together as a final step.

I guess this probably sounds easiest. Looking at the assembly listing, it looks like using L_MAP[temp] = All_Levels[level][temp]; makes a call to pushax, which is probably what's messing things up. It'll save me from banging my head against the wall with assembly at least.


Top
 Profile  
 
PostPosted: Tue Oct 24, 2017 7:00 pm 
Offline

Joined: Tue May 09, 2017 5:03 am
Posts: 11
So I tried concatenating two separate projects and while it does solve the memcpy problem, it actually used up 1k more space than my brute-force method. I think the added stability will be worth it in the future though, and I'm not exactly hurting for space. Just thought it was funny that it worked out that way though


Top
 Profile  
 
PostPosted: Tue Oct 24, 2017 11:58 pm 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 580
Your transition, relying on the same address, is a bit fragile. I'd recommend writing the copy function in asm, and storing it in RAM, so you never have to jump to different code under the same function. You can achieve this by putting it to the DATA segment.


Top
 Profile  
 
PostPosted: Wed Oct 25, 2017 10:55 am 
Offline

Joined: Tue May 09, 2017 5:03 am
Posts: 11
calima wrote:
Your transition, relying on the same address, is a bit fragile. I'd recommend writing the copy function in asm, and storing it in RAM, so you never have to jump to different code under the same function. You can achieve this by putting it to the DATA segment.

I tried writing a copy function in asm, but I was having trouble wrapping my head around how to do it. I read some other topics about it, but for some reason I'm just finding it difficult to understand how to do it.

As of right now I have any code related to switching banks stored at $FF00. I'm not switching banks particularly often, only once at the start of each level to fetch the array data, so it's not like I'm doing it multiple times per cycle. Is it still something that could give me headaches later on?


Top
 Profile  
 
PostPosted: Thu Oct 26, 2017 6:46 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 580
It'll probably work fine, but things like cc65 updates could break it.

You can cheat with cc65 to kickstart the asm. Use the memcpy version, and compile with -Ois and the memcpy call should be inlined.


Top
 Profile  
 
PostPosted: Thu Oct 26, 2017 3:21 pm 
Offline

Joined: Tue May 09, 2017 5:03 am
Posts: 11
calima wrote:
It'll probably work fine, but things like cc65 updates could break it.

You can cheat with cc65 to kickstart the asm. Use the memcpy version, and compile with -Ois and the memcpy call should be inlined.
I might give that a try. Since I have a fixed length for the arrays it could give me the opportunity to trim out some needless code.


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

All times are UTC - 7 hours


Who is online

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