News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

banked_call -sdcc

Started by arnoldemu, 13:37, 22 August 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

arnoldemu

Has anyone tried using "banked_call" under SDCC??

It appears it may work, but I can't tell.

If it does work then games using extra RAM/ROM would be easier under SDCC.


Octoate

I haven't looked at it yet, but I am interested in how to use it (if it works) with the CPC. Do you have any example on how to use "banked_call" with SDCC?

arnoldemu

Quote from: Octoate on 09:50, 23 August 14
I haven't looked at it yet, but I am interested in how to use it (if it works) with the CPC. Do you have any example on how to use "banked_call" with SDCC?

This is related to the 8051:
8051 Code Banking · adamdunkels/contiki-fork Wiki · GitHub

Looking at the z80 code generation it emits:


call banked_call
defw address
defb bank


8051 emits similar, but also has a "banked_end".

The best I could come up with so far is this:


.module banked_call
.globl banked_call

;; code is emitted as follows:
;; 
;; call banked_call
;; defw address
;; defw bank


.AREA _CODE

;; at start of banked call we have:
;; 
;; stack:
;; data after banked address

;; at end of banked call we want:

;; stack:
;; bank address to call (added last)
;; banked_ret
;; cur_bank
;; return address after banked_call (added first)

banked_call:
pop iy

push iy
pop hl
inc hl
inc hl
inc hl
inc hl
push hl

ld hl,(cur_bank)
push hl

push af
;; now set page
ld a,(iy+2)
call set_page
pop af


ld hl,banked_ret    ;; go via banked_ret
push hl

;; function to go to
ld l,(iy+0)
ld h,(iy+1)
push hl
ret

set_page:
push bc
;; store rom page selected
ld (cur_rom_page),a
;; change rom page
ld b,&df
or &80
ld (c),a
pop bc
ret


banked_ret:
pop hl        ;; get return rom page
push af
ld a,l        ;; make it current
call set_page
pop af
;; and return back to the code
ret

.AREA _DATA
cur_rom_page:
defw 0



The idea here is that:
1. the current rom page is remembered in a variable, this is needed so we know which bank to return to.
2. the banked_call would be in common memory so that you can call into it from banked memory.
3. when the banked call is done, it reads the data, it sets up the stack with:
a) the current bank so it can return to it.
b) a call to banked_ret which performs the bank restore.
c) the address to go to
d) the address to return from

The code is setup for cartridge currently, but could be adapted for banked ram (e.g. on x-mem by changing the out to set the bank).

I think to make it work we would need to setup the appropiate sections and at a location that we can use e.g. &c000 for cartridge and &4000 for banked ram.

I haven't got much furthur than this.



arnoldemu

I tested it further using the latest sdcc snapshot. The address is filled in but the bank is blank. It appears it may be valid if z80asm is used because it replaces the emitted variable with a special macro. With asxxxx it is not implemented. On 8051 if you choose large address it appears to extend the address to 3 bytes length compared to the default. I tried similar with sdcc but I was not successful yet.

Answer currently is that banked calls are not supported.

arnoldemu

... 3 years later...

I have patched the linker so that I can define a limit for each base/segment. I hope the sdcc team will accept the patch or make a similar change themselves.

This means it will now warn if you have too much code/data in each segment. I need this because our ram or cart pages are 16KB and need a way to tell the programmer when they have filled a bank.

I have also patched the assembler. Now I can build and link and make a gx4000 cart.

It is simple, at the top of each c file add this:


#pragma codeseg BANK1


BANK1 is not hard coded it is defined in the linker. Add one in each c file, define all functions as __banked.

Now define a link script. To define which cart page to use you define address as 24-bit in the linker.
e.g.

0x1c000

1 is the cart page (&80+1), &c000 is the address of the page in memory space.

1 link script for the entire cart. Multiple c files per bank is easiest but you don't need to as long as the code has the appropiate codeseg set.

At this time, I have a bin file with lots of these sections spread across the file. I need to write another program to take the data and join it together so I can use buildcpr to make an emulator file.

There are still some things to resolve, use of named spaces and banked regions are not compatible.

But progress...

arnoldemu

I made more progress on this about a month ago...

I updated the linker so I could define the destination address in the file so that I don't need to have a tool to join the parts together.
So now I can define both their dest cart page, the length and the location in the binary file. buildcpr can then take this and make a cpr. One less step to do :)

I also attempted to make a test game that would demonstrate how to use it.

I still need to resolve the named space/banked region stuff though.





Powered by SMFPacks Menu Editor Mod