Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - devkitSMS banking code questions

Reply to topic Goto page 1, 2  Next
Author Message
  • Joined: 27 Apr 2021
  • Posts: 19
Reply with quote
devkitSMS banking code questions
Post Posted: Fri Feb 17, 2023 7:45 am
Hi everybody

I have somes questions about banking code with sdcc and devkitSMS.

For now, I have a projet with many .c files and a create the rom with the 'ihx2sms' tool.

If I understood correctly I must switch to the 'makesms' tool to use the code banking, is that right ? But everytime I compile with it it says : "Fatal: Bank 0 overflow"

For now, my projet contains 31140bytes of code in bank 0 & 1.
So I assume I need to split all my code into 16k of code to work ?

And another question : can I compile multiple files to the same code bank ? something like this :

sdcc -c -mz80 --codeseg BANK1 items.c
sdcc -c -mz80 --codeseg BANK1 chests.c
sdcc -c -mz80 --codeseg BANK1 maps.c


Is it possible or do I need to put ALL my code into the same .c file ?

Thank a lot
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Feb 17, 2023 8:23 am
code banking requires that all the banked code be compiled in modules that are 16 KiB max, but if two modules can fit the same bank they can be linked together.

Btw you have to declare a code segment for each (could be any string you want, but it's easier just to use 'BANK' and a progressive number.) when compiling them.

Example: say your player code is in player.c

sdcc -c -mz80 --codeseg BANK1 player.c


and your enemies code is in enemies.c

sdcc -c -mz80 --codeseg BANK2 enemies.c


then you link with your main module (which is not banked) and the assets (say in bank 3 to bank 5) like this for example:

sdcc -o output.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_BANK1=0x14000 -Wl-b_BANK2=0x24000 -Wl-b_BANK3=0x38000 -Wl-b_BANK4=0x48000 -Wl-b_BANK5=0x58000 sms_crt0.rel main.rel smslib.rel player.rel enemies.rel bank3.rel bank4.rel bank5.rel


note how the instructions to the linker works:
- -Wl-b_BANK1=0x14000 means 'BANK1' goes to the ROM bank1 and maps to CPU address 0x4000 (that's slot 1 for code switching)
- -Wl-b_BANK3=0x38000 means 'BANK3' goes to the ROM bank3 and maps to CPU address 0x8000 (that's slot 2 for assets switching)

then of course you use makesms for converting the created ihx file to the final sms file.

also:
Quote
can I compile multiple files to the same code bank?

yes, exactly in that way you used as an example
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Fri Feb 17, 2023 11:05 am
Naarshakta wrote
But everytime I compile with it it says : "Fatal: Bank 0 overflow"

I think this may be due to a typo in the README docs in devkitSMS, which suggests
-Wl-b_BANK2=0x8000 -Wl-b_BANK3=0x8000

rather than
-Wl-b_BANK2=0x28000 -Wl-b_BANK3=0x38000

as sverx illustrates above.

So OP, do very carefully copy what sverx has written above when you build.

(@sverx I mentioned this the other day in passing but I'm sure it got lost in amongst all the other stuff!)
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Feb 17, 2023 11:23 am
well, it's complicated...

until some time ago, SDCC linker couldn't map code or data to ROM banks - only to CPU addresses - so you had to have your code use the first 32 KiB and map all the data at 0x8000. ihx2sms would then take care of creating the ROM in the correct way, provided you would link the data banks in the correct order.

newer SDCCs supports banked code, and the linker accepts 'virtual' addresses, which are basically the number of ROM banks << 16 + the CPU address to be mapped (typically 0x4000 for code and 0x8000 for data)

so, yeah, one day I will remove all the references to the 'old' approach - which is anyway still valid if you don't need banked code.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Fri Feb 17, 2023 1:49 pm
sverx wrote
so, yeah, one day I will remove all the references to the 'old' approach - which is anyway still valid if you don't need banked code.


By banked code, you mean e.g. functions invoked via the trampolines, as opposed to purely assets? Or does that include assets converted to C `const` data as per the default behaviour of `assets2banks`, or only when you use `--compile` to generate rels?

I'm not running any of the implicitly banked (trampolined) code as far as I know, and started off running assets2banks with `--allowsplitting --singleheader=...` to generate both C and and a header file; and then used `-Wl-b_BANK2=0x8000` in my linker stage and that didn't work - the assets aren't in the right place at runtime. (I thought that was the overflow problem the OP mentioned but of course that must be happening earlier at the asset bundling stage, apologies).

Only changing to `-Wl-b_BANK2=0x28000` fixed the problem.

I'm running SDCC snapshot 4.2.12 #13827
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Feb 17, 2023 2:11 pm
willbritton wrote
By banked code, you mean e.g. functions invoked via the trampolines, as opposed to purely assets?


yes. without banked code, your code will be fixed on bank0 and bank1, so it can be max 32 KiB, but you can page assets in slot 2, so your assets will start from bank2 and you can have as many total banks as you can fit in your ROM.

willbritton wrote
and then used `-Wl-b_BANK2=0x8000` in my linker stage and that didn't work
Only changing to `-Wl-b_BANK2=0x28000` fixed the problem.


if you use `-Wl-b_BANK2=0x8000` then you have to use ihx2sms, not makesms.

if you use `-Wl-b_BANK2=0x28000` then you have to use makesms, not ihx2sms.

if I were you, I would use the latter (the former was because there was no other choice back then...)
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Fri Feb 17, 2023 2:26 pm
sverx wrote
if you use `-Wl-b_BANK2=0x8000` then you have to use ihx2sms, not makesms.

if you use `-Wl-b_BANK2=0x28000` then you have to use makesms, not ihx2sms.

if I were you, I would use the latter (the former was because there was no other choice back then...)

Aha - that's the missing piece of the puzzle, thank you!

I am using makesms, but not sure why because the docs still kind of point one towards ihx2sms, perhaps I just read that it was newer in the notes and decided newer was better :D

Still, I'll carry on using makesms and the virtual addresses as you say.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Feb 17, 2023 2:41 pm
yeah, the documentation can create some confusion sometimes...

in my plan, everything before the ADVANCED: How to use more than 32KiB of code in your SMS/GG ROM ('banked code') section works fine on its own, but if you need more than 32 KiB of code then you read this last section which instructs you of the differences...
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 545
  • Location: Málaga, Spain
Reply with quote
Post Posted: Fri Feb 17, 2023 6:21 pm
Ummm... Even now i am using the "old approach" to access banked code. This year i have about 96kb of code... 32 kb in main banks and four other banks containing the custom scene code.

The trick IS to switch banks before calling the banked function... And not to try to switch bank into a banked function.... All functions which load banked data (loadtiles... Tilemaps or whatever you want to load) reside in banks 0 or 1 so the bank switching is safe.

So... Please sverx... Dont touch anything!!! Smslib is perfect like It IS!!!!
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Feb 18, 2023 11:21 am
@eruiz00 - I know you built your own explicit code bankswitching in slot 2 (which is kind of weird but as long as it works it's no problem for me) so don't worry as I won't remove anything that you're using.

Still, next time I hope you will try the transparent code bankswitching provided by latest SDCC + devkitSMS. I think it's way much easier to handle compared to what you're doing now.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Apr 2021
  • Posts: 19
Reply with quote
Post Posted: Sun Feb 19, 2023 9:36 am
eruiz00 wrote
Ummm... Even now i am using the "old approach" to access banked code. This year i have about 96kb of code... 32 kb in main banks and four other banks containing the custom scene code.


How do you achieve this ? I tried to do banked code "manually" but it doesn't work at all :o
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sun Feb 19, 2023 10:46 am
Naarshakta wrote
How do you achieve this ? I tried to do banked code "manually" but it doesn't work at all :o


I would say it's more complicated than just using what's already available with devkitSMS, and it also means that your banked code won't be able to map assets into slot2 since it would remove the running code itself from the CPU address space the moment you map an asset.

If something isn't clear about how to use SDCC banked code or the way you need to link modules to make that work just let me know.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Apr 2021
  • Posts: 19
Reply with quote
Post Posted: Mon Feb 20, 2023 2:13 pm
Okay ! I wanted to thank you all !

I successfully converted all my code to a more flexible version with the transparent bank switch.

I am now able to code everything I want for my game ( *.* )


  View user's profile Send private message
  • Joined: 28 Jan 2017
  • Posts: 545
  • Location: Málaga, Spain
Reply with quote
Post Posted: Mon Feb 20, 2023 4:46 pm
I am going to explain my technique, which is very easy, and, I think, it could be better than let the compiler to manage this question...

example:

In bank 0:

function loadtiles(unsigned int basetile, void *tiles, unsigned char bank)
{
pushBank(bank);
loadtiles(tiles,basetile);
popBank();
}

void main(void)
{
changeBank(6);
loadStage6();

...

changeBank(27);
loadStage27();

}

... in bank 6

loadStage6()
{
loadTiles(256,tiles_for_stage6_bin,tiles_for_stage6_bin_bank);
}


This will work always as the bank switching to load the assets is done in the bank 0 loadtiles function. It is easy to see that, with the functions which need a bank switching in banks 0,1, you have unlimited space to code the custom scene-enemy-whatever you want functions, without the compiler new feature.

I found, also, very convenient this way of work... because, if you have constants associated to the banked code (by example, constant strings with a conversation between the the player and a boss, an uncompressed map which you don't want to copy to ram, by example), will remain in the same bank as the code which use them. You have the control over the code and the assets.

It is only an option, a way to do this. The developer who get to the moment of having to develop code in banks should be enough mature to know which option is the better for his project.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Feb 20, 2023 6:51 pm
it's indeed a possible solution, and I'm happy you find that solution adequate to your approach... after all, there's rarely a single way to achieve something.

But I don't think this is easier or any better than what the current SDCC compiler + dev kit can offer 'out-of-the-box'

For instance, up to 16 KiB of code can be dedicated to a single stage plus all the assets you might ever need - not limited to just one bank, as they are assets anyway. Banked code can call any SMSlib function directly, the same way you would do with regular non-banked code. And banked code can explicitly map assets because they never overlap addresses. Banked code can call other banked code too, because the trampolines will save the caller's code bank and restore that on return - a sort of FAR call, if you've ever worked with x86 code.
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 545
  • Location: Málaga, Spain
Reply with quote
Post Posted: Mon Feb 20, 2023 7:13 pm
Yeah! I supposed that you are right.... One fault of mine IS that It IS hard for me to change the way I make the things.... Interesting your point about the assets.... (The compiler will change the bank to the asset bank and then Will call to sms_loadtiles... And Will return back to the previous selected bank if sms_loadtiles IS called fron a banked function in a bank different fron the tiles? That IS a bunch of things to be automated by the compiler :D

Worst thing fron the banked code IS that (at least me) one dont have to optimize the code (mainly search common functions and behaviours and pack them into shared functions, and optimizing everyrhing not only for speed... Also for size) to keep the code inside that 32kb... I see Silver Valley now and i feel It were a BIG work to put all these logic in the first two banks!!!!
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Feb 21, 2023 8:36 am
mmm, no, the compiler doesn't automatically map any asset, that still works as it always worked, by calling a
SMS_mapROMBank(some_asset_bank)
before accessing the asset data.

But the compiler transparently does code bankswitching for the functions that are declared __banked. In short, when a banked function is called, the compiler invokes some SDCC library functions that in turn use two small functions that are in devkitSMS' crt0 code that are the ones providing the bankswitching -- see get_bank and set_bank here.
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14688
  • Location: London
Reply with quote
Post Posted: Tue Feb 21, 2023 10:23 am
Asking some questions out of curiosity as of course I do all this in asm…

Does it auto-choose banks for functions or do you pick them yourself? I love auto-bank-packing in WLA DX…

If it does pick banks, does it optimise to try to keep related functions in the same bank?

Does calling a banked function that happens to be in the same bank get resolved to a “near call” or is it always a “far call”?

It seems that in general it would be easiest therefore to use slot 1 for all the code banking and slot 2 for the assets. This would avoid a lot of trouble with having to try to keep banked assets alongside the banked functions that operate on them - although doing that would be more efficient if it means less time spent messing with banks and trampolines in the pathological case.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Feb 21, 2023 11:21 am
there's no automatic bank picking - you basically write your code in modules and, in its simplest form, every module has its own bank with 16 KiB of ROM space for it, so you assign banks from BANK1 onward to your modules - say player.c compiles into BANK1 enemies.c into BANK2 and so on... but of course you can save some ROM space if you have some small modules that can fit in the same bank with other(s).

regarding calling a banked function from the same module - yes, it will still result in a 'far call'. But the catch is: not every function in a module needs to be a __banked one, in fact only those called from other modules need to be. So in a given module you usually have just a few banked functions and the rest are 'regular' ones. For instance in a player.c module you might just have a single handle_player() banked function and all the rest of code is 'local' and should not be declared as __banked.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Tue Feb 21, 2023 1:20 pm
sverx wrote
So in a given module you usually have just a few banked functions and the rest are 'regular' ones. For instance in a player.c module you might just have a single handle_player() banked function and all the rest of code is 'local' and should not be declared as __banked.

Interesting. I suppose that it often makes more sense to think about what code you might want to bank out of the first 32KB, rather than blanket assuming that all code is bankable.

Oh and to one of my previous points - the __banked modifier only applies to functions, right - not variables?
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Feb 21, 2023 1:29 pm
willbritton wrote
the __banked modifier only applies to functions, right - not variables?


functions only. variables are in RAM and that's always mapped to CPU address space (fortunately!)
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14688
  • Location: London
Reply with quote
Post Posted: Tue Feb 21, 2023 2:24 pm
What about constants?

Is calling an unbanked function in a banked chunk a compile-time error or just a footgun?
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Tue Feb 21, 2023 2:35 pm
Last edited by willbritton on Tue Feb 21, 2023 2:42 pm; edited 1 time in total
Maxim wrote
What about constants?

Think constants map to assets and for that you need to use the "manual" bank switching as per sverx's above comments.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Feb 21, 2023 2:39 pm
the compiler compiles each module separately and function calls are generated according to the function attributes, which means that at run time if you call a function that is 'unbanked' this could result in footgun if that function is declared in a different banked module that has been allocated (by the linker) into a different bank.

so you can safely call any regular function that is either in the same banked module or in a separate banked module that you link together or in any module that will be always available because in bank 0 (main code, library code, etc...)

edit: about constants - if you mean ROM data that isn't an external asset, for instance LUTs, you either put them in the main module if you need them to never be mapped out, or you put them locally in the module needing them. Third option, you assemble them in a separate module that you will 'manually' map as if they were assets... but that's probably the less convenient option.
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 545
  • Location: Málaga, Spain
Reply with quote
Post Posted: Tue Feb 21, 2023 6:23 pm
In my experience, I think the SDCC autobank feature is of utility, but I would plain a general engine for the game, with the functions with bank switching into the first two banks, and then the custom by scene game logic (enemy definitions, custom scene code, animations, etc.) as banked code, letting the compiler to optimize the banks (it does a great job, like assets2banks.. it is hard to fill the space so optimized manually), and keeping the engine itself bank status free.

This year game is done this way... almost 32kb for the common functions... and several banks of code for the scenes. And the assets are mapped by assets2bank, as they are used only from general engine functions (mainly load_tiles, load_tilemap, play_psg, etc.) Even there are not trouble with the vblank handler, when called when you are inside a banked function.
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Thu Mar 23, 2023 3:44 pm
sverx wrote
there's no automatic bank picking - you basically write your code in modules and, in its simplest form, every module has its own bank with 16 KiB of ROM space for it, so you assign banks from BANK1 onward to your modules - say player.c compiles into BANK1 enemies.c into BANK2 and so on... but of course you can save some ROM space if you have some small modules that can fit in the same bank with other(s).

Just coming back to this @sverx - I just ran into a problem where I'm over capacity in bank 0. Afk right now, but before I left I briefly tried moving my assets from bank 1 to 2, and then directing the largest module to target bank 1 neither of which seemed to help.

To clarify, is the following true: that by default code will target bank 0 but if you hit 16KiB it will not automatically roll into bank 1?
If so, is there any way to specify a 16KiB code segment spanning banks 0 and 1?
If not, is there an easier way to identify exactly what the final size of each module will be? My rel file is 64KB which is obviously not the final object size.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Mar 23, 2023 3:52 pm
If you're not using code paging, your code can be max 32 KiB, your assets can use as many 16 KiB pages as you want, from bank 2 onwards.

If you're using code paging, each of your code 'modules' can be only 16 KiB at most, and page 0 (the code that will be never paged out) is limited to 16 KiB too so if this is overflowing you have to move something into a separate code module.

In any case assets should go into separate banks, unless you have a good reason for not doing that.

You can see the size of each module looking at the map file.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Thu Mar 23, 2023 3:57 pm
Hmm, okay thanks.

I'll check the map file when I get back but I'd be amazed if the code's as big as 32K.

I'm not using code banking but I am using makesms - is that my problem?

EDIT: I'm almost certain the code can't be 32K because right before the issue started happening my assets were in bank 1 so the code must have fit in bank 0 I think.
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 545
  • Location: Málaga, Spain
Reply with quote
Post Posted: Thu Mar 23, 2023 4:00 pm
I check the .map file fron the compiler to know how many space i have used in a bank... So i can Split the code in different banks (manually) and control where i put the code.

Like i said before... I found interesting to keep control of the code and the constants to define scenes or other behaviours (those which are not assets) to keep the access to banked constants from banked code (as i control that they are in the same bank).
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Mar 23, 2023 4:37 pm
willbritton wrote
I'm not using code banking but I am using makesms - is that my problem?


No, it shouldn't. You can use makesms even without using code banking.

willbritton wrote
I'm almost certain the code can't be 32K because right before the issue started happening my assets were in bank 1 so the code must have fit in bank 0 I think.


So if you had the assets starting from bank 1 and now from bank 2 check if you're linking them correctly. Your code can extend over bank 0 and bank 1 and won't ever be paged out. Make sure you're not linking an old bank1.rel (in fact, you shouldn't have any bank1.rel at all here...)
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Thu Mar 23, 2023 6:34 pm
According to the map file the code segment is 15662, which fits with my earlier observation about the assets being in slot 1.

The code segment starts at 0x0200 (I think?) - so I make that 16174 although I guess I'm forgetting about something else sitting on top of it perhaps?

In any case, definitely not > 32K.

sverx wrote
Make sure you're not linking an old bank1.rel (in fact, you shouldn't have any bank1.rel at all here...)

Starting clean each time - not an old bank1.rel.

sverx wrote
So if you had the assets starting from bank 1 and now from bank 2 check if you're linking them correctly.


This is what I'm doing to work with makesms:

sdcc -L$(SMSLIB_DIR) -o$@ -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_BANK2=0x28000 $(SMSLIB_DIR)/crt0_sms.rel main.rel <other rels...> SMSlib.lib PSGlib.lib



sverx wrote
willbritton wrote
I'm not using code banking but I am using makesms - is that my problem?


No, it shouldn't. You can use makesms even without using code banking.


I just tried with ihx2sms (and equivalent linker change to `-Wl-b_BANK2=0x8000`) and now it's building fine again, so clearly I'm doing something wrong with makesms. Would be interested to hear whether my linker invocation was correct above?
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Mar 24, 2023 8:00 am
willbritton wrote
I just tried with ihx2sms (and equivalent linker change to `-Wl-b_BANK2=0x8000`) and now it's building fine again, so clearly I'm doing something wrong with makesms. Would be interested to hear whether my linker invocation was correct above?


Reading your explanation hinted me there could be a bug in makesms, and in fact I think I just identified one. So please use ihx2sms for your non banked code programs in the meantime.

edit: it turned out it wasn't so trivial as I suspected initially so I ended up refactoring some part so that now makesms should be able to replace ihx2sms in -hopefully- any situation. But I won't remove ihx2sms anytime soon anyway, so there's always a safety net should there be one more issue I didn't spot.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Fri Mar 24, 2023 11:40 am
Amazing, thanks @sverx!

I'll keep using ihx2sms for the next few days until my competition entry is "finished" and then I'll switch back to test the latest makesms and send you feedback.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Fri Mar 24, 2023 10:06 pm
I remember trying to use makesms but could not make it work (I was not banking code). So I have using ihx2sms and it has worked flawlessly, but of course if one day I want to bank code, I will have to figure out how to use makesms as well :)

I found it easy with ihx2sms has you simply have to stack your 0800 banks and you are good to go.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Mar 25, 2023 1:29 pm
ihx2sms was the only possible solution (at least that I could find) when SDCC didn't write 'banked' addresses to its IHX output.
Later, when SDCC added transparent bankswitching for z80 code, they also provided a better IHX output that could handle 'banked' addresses, and that's when makesms was created.

But, I would say until now, ihx2sms was the tool for devkitSMS projects which didn't need banked code and makesms wasn't meant to be used there... now makesms should be able to replace ihx2sms in that situation too, so to have less tools to maintain in the long run.

But I'm not the guy that removes anything easily so ihx2sms won't disappear anytime soon, no worries.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Mon May 29, 2023 10:07 am
Jumping back on this topic again as I have a few questions about code banking, which I will probably be using in a new game (the current one is almost complete).

I read the entire discussion and think I understood many things, but still have some questions, sorry if this has you repeating yourselves haha.

My understanding is that MS/GG sees two banks of code and that's it :
bank 0 which is 16 KB
bank 1 which is 16 KB

And then we can swap data in bank 2 16 KB chunk as well

Using ihx2sms, I never had to worry about bank 0 and 1. Overall, my code fits into 32 KB and I am good with it.

Tomorrow, if I want to bank code, I understand that the swapping effect will take place in bank 1.

So first question :
How do I decide which code is in bank 0 and which code is in bank 1 ? Does bank 1 become something "else", in the sense that it should be considered a swappable bank just like any other code bank (2, 3, 4 etc...) and will it be "by default" loaded in bank 1 ?

If this is the case, it probably answers question 2 (which I read some info previously, but I need to ask again to make sure) :
What happens if banked code (for example in bank 3) calls a function from bank 0 ? from bank 1 ? from bank 2 ?
I get it that bank 0 should not be an issue. Bank 2 I think I read it was going to work (will it change bank automatically ?). But bank 1 is still a bit of a mystery here, unless it behaves exactly like any other code bank of course.

Maybe that it is wiser to have self contained methods banked, to avoid jumps and possible issues, as much as possible.

Do I need to use a method to select the right bank before a function call, just like I do to select the data banks ?

Could you be kind enough to put an example of a compiling command that contains let's say 3 banks of code and 3 banks of data ? Just to be sure on how it would look with the "virtual addresses" ? That would be a great help.

Thanks a lot !

Edit : maybe this answers my last question (seen above) :

sdcc -c -mz80 --codeseg BANK1 player.c

sdcc -c -mz80 --codeseg BANK2 enemies.c

sdcc -o output.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_BANK1=0x14000 -Wl-b_BANK2=0x24000 -Wl-b_BANK3=0x38000 -Wl-b_BANK4=0x48000 -Wl-b_BANK5=0x58000 sms_crt0.rel main.rel smslib.rel player.rel enemies.rel bank3.rel bank4.rel bank5.rel
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 879
  • Location: Spain
Reply with quote
Post Posted: Tue May 30, 2023 10:28 am
I "believe" (As I haven't tried myself yet), that if you use the feature on SDCC 4.x (not the manual way that Eruiz00 uses), banking happens automatically. You have to mark the functions as banked and compile them specifically as it's suggested https://github.com/sverx/devkitSMS/blob/master/README.md#advanced-how-to-use-more-than-32kib-of-code-in-your-smsgg-rom-banked-code.

The code that's not banked will be in slot 0, so no banking code cannot be bigger than 16kb.

Whenever you call a function on banked code, it'll map the right bank in Slot1, and execute from there. You can call code from another code bank and it'll bank again when being called.

You can continue banking any resource you want in Slot2, by hand as we've done usually.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Tue May 30, 2023 4:18 pm
kusfo wrote
I "believe" (As I haven't tried myself yet), that if you use the feature on SDCC 4.x (not the manual way that Eruiz00 uses), banking happens automatically. You have to mark the functions as banked and compile them specifically as it's suggested https://github.com/sverx/devkitSMS/blob/master/README.md#advanced-how-to-use-more-than-32kib-of-code-in-your-smsgg-rom-banked-code.

The code that's not banked will be in slot 0, so no banking code cannot be bigger than 16kb.

Whenever you call a function on banked code, it'll map the right bank in Slot1, and execute from there. You can call code from another code bank and it'll bank again when being called.

You can continue banking any resource you want in Slot2, by hand as we've done usually.

Thanks, this helps a lot :)
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Tue Aug 29, 2023 8:24 pm
Hello everyone,

Hope you are doing well.

This topic has been helpful, I have been able to setup my new workspace with makesms and have put my first functions in banks.

I also understood the values to put after the bank number (x4000 for code, x8000 for data). It was obscure at first but reading your past discussion helped. So this sounds good.

One question : when I get beyond bank 16, should I put something like this ?

-Wl-b_BANK1=0x14000
...
-Wl-b_BANK20=0x144000 ?

This means writing the number of the bank on two chars and then put 4000 or 8000 after it ? Thanks.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Aug 30, 2023 8:09 am
cireza wrote
[...] when I get beyond bank 16, should I put something like this ?

-Wl-b_BANK1=0x14000
...
-Wl-b_BANK20=0x144000 ?

This means writing the number of the bank on two chars and then put 4000 or 8000 after it ? Thanks.


Exactly. You go up to 0xF4000 for instance, then 0x104000 is the next one and so on.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Wed Aug 30, 2023 3:36 pm
sverx wrote
Exactly. You go up to 0xF4000 for instance, then 0x104000 is the next one and so on.

Thanks sverx.

I have a few more points, not blocking but if you have an idea on how to improve what I do, it will be appreciated.

If you take a look at my current setup (screenshot), I have decide to put in a dedicated bank what I call "handlers". Basically I create handler.h/c files for a specific purpose. In this case managing my world map.

I added banked to the file name to sort things on my side. This file is also being compiled in a dedicated bank with codeseg. All of this work.

Practically though, I have a few questions.

By definition, all functions in this file will be in the bank. Let's say that my handle_worldmap function is the only one that is really public (called by the main) and everything else is private to this file. Do I need to put the __banked after every "private" function ?

(my .h file only contains 1 line :
void handle_worldmap(void) __banked;
)

eclipse is putting some warnings on the entirety of the functions as well (in yellow), I need to find a way to remove this because it is super annoying. It seems that for him, the functions have become Unused : "unused declaration of function".

One other point : bottom left (in red), I do get some errors/warnings when compiling and don't understand why yet.
Capture.PNG (109.01 KB)
eclipse
Capture.PNG

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Aug 30, 2023 4:21 pm
private or public in this context are not the correct words, but I think I get what you mean.

so the answer is: in a source file that gets compiled to a banked code, not every function needs to be declared as __banked, but only those that are called from a different module, and those are the only ones you actually need to have in the header file for that module.

so in short in any of those you'll have 1+ __banked functions and all the others don't need the __banked attribute.

as for the compiler warnings, you can ignore them, it's SDCC nonsense.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Wed Aug 30, 2023 8:25 pm
I use private/public naming for my personal organization, even though the concepts do not exist in C. This is simply a guideline for me to know where to put my functions and which ones to expose in the header files for other files to use.

I started coding the streaming of my world map on SMS this evening. Managed to make this work cleanly to the left and right for now. Having to stream 8 pixels by 8 pixels in the left column is quite constraining. Realized that I had to stream then scroll to the right, but to the left actually you must scroll first then stream :) And I work with 16 pixels metatiles of course, makes it even simpler haha. But I am not complaining, this hardware is fantastic overall. It simply works and is quite straightforward.

Going to add vertical scrolling next and see how it behaves. I don't have as much headroom as on GG that's for sure, can't stack as many wait_for_vblanks haha. Fun times ahead !

But I don't want to derail the thread anyway. Thanks for the response :)
  View user's profile Send private message
  • Joined: 09 Aug 2021
  • Posts: 106
Reply with quote
Post Posted: Wed Aug 30, 2023 8:38 pm
sverx wrote
so the answer is: in a source file that gets compiled to a banked code, not every function needs to be declared as __banked, but only those that are called from a different module, and those are the only ones you actually need to have in the header file for that module.

such functions should be declared as static
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Aug 31, 2023 7:18 am
toxa wrote
such functions should be declared as static


true, but as long as you don't recycle function names across modules it really doesn't matter. But it's a good suggestion indeed!
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Thu Aug 31, 2023 11:23 am
My code is certainly not state of the art. What matters the most is having a game that runs fine !

I will be using the static kerword for these functions from now on.
  View user's profile Send private message
  • Joined: 09 Aug 2021
  • Posts: 106
Reply with quote
Post Posted: Thu Aug 31, 2023 2:10 pm
sverx wrote
true, but as long as you don't recycle function names across modules it really doesn't matter. But it's a good suggestion indeed!

that keeps yourself from calling functions which are not supposed to be called from outside (not the part of your own public interface of the module). that is the C way to declare public/private functions or other objects. ability to reuse names is minor to the main idea of that feature. :)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3762
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Aug 31, 2023 2:16 pm
toxa wrote
sverx wrote
true, but as long as you don't recycle function names across modules it really doesn't matter. But it's a good suggestion indeed!

that keeps yourself from calling functions which are not supposed to be called from outside (not the part of your own public interface of the module). that is the C way to declare public/private functions or other objects. ability to reuse names is minor to the main idea of that feature. :)


good point!
  View user's profile Send private message Visit poster's website
  • Joined: 10 Aug 2023
  • Posts: 31
Reply with quote
Post Posted: Wed Sep 06, 2023 11:09 pm
Is there a large performance hit when calling a banked function?
  View user's profile Send private message
  • Joined: 04 Jul 2010
  • Posts: 539
  • Location: Angers, France
Reply with quote
Post Posted: Thu Sep 07, 2023 7:08 am
Not null, but not far to be

You'll need few cycles to load the bank (where the function is) and restore after.
  View user's profile Send private message
Reply to topic Goto page 1, 2  Next



Back to the top of this page

Back to SMS Power!