It is currently Mon Oct 23, 2017 1:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Aug 31, 2010 4:16 am 
Offline
User avatar

Joined: Tue Apr 28, 2009 4:12 am
Posts: 469
Hoping someone has a suggestion on how to do this elegantly as I can't fathom it out.

I want to split my editor over two 16k banks (MMC1) but there are some common routines and tables that need to be accessed whichever of the two PRG banks the editor is currently in.

My idea was to duplicate these common elements in both editor banks at the same address so you can just call them from anywhere in the editor. Problem is, the labels end up being duplicated too and you get errors of course.

However, I'm unsure about how to go about it. I was trying to mess around with .export and .import but I got myself in a lot of knots. I was hoping there'd be a simple way to do it in the memory configuration file for ld65.

Any advice would be very welcome. :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 4:40 am 
Offline

Joined: Thu Oct 05, 2006 6:29 am
Posts: 911
If the code is location-independent you could compile it separately and incbin the resulting binary at all the places where you need it.

Another solution would be to create macros of them (essentially making all local labels anonymous).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 4:49 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
Compile and link it separately, and write out a map file. In your main program, incbin the result in its own SEGMENT. Write a native program (in C, Perl, Python, etc.) to translate the map file into a file that the main program can include.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 5:01 am 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
I just tried this and it works well, assuming I'm understanding the question. First, assemble each segment separately, so that only the exported symbols can clash. Then just include the duplicated code in each segment but don't export its names. No incbin or anything. Full source (uses 16-byte segments to make it easy to see in hex editor): ca65_segments.zip

I noticed Neil mentioned he wants the controller routines at the SAME addresses in each. To achieve this, include them at the beginning of the segments, so they always assemble the same in each.

Code:
; controller.s
    read_joy:
        ...
        rts

; common.s
    .export table
   
    .segment "COMMON"
    table:
        ...

; seg1.s
    .export foo
    .import table
   
    .segment "SEG1"
       
        .include "controller.s"
       
    foo:
        ...
        jsr read_joy
        ...
        lda table,x
        ...
        rts

; seg2.s
    .export bar
    .import table
   
    .segment "SEG2"
       
        .include "controller.s"
       
    bar:
        ...
        jsr read_joy
        ...
        lda table,x
        ...
        rts

; build
ca65 common.s
ca65 seg1.s
ca65 seg2.s
ld65 common.o seg1.o seg2.o


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 6:01 am 
Offline
User avatar

Joined: Tue Apr 28, 2009 4:12 am
Posts: 469
Thanks for the help and ideas.

With blargg's example I managed to get the code building but have ran into another problem. All of my ZP/RAM vars are defined in one .h file and so I now need to .export everything so the other 'modules' can use the vars.

The only option seems to be to .export every variable and then .import the definitions (or use the auto-import switch for ld65?) but as I've got about 600 variables defined, if there's a less labour-intestive way to avoid having to change the whole .h to to export everything, I'd really appreciate some info.

Or could I turn the .h file into a 'library'?

:)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 6:27 am 
Offline
User avatar

Joined: Sun Sep 07, 2008 7:27 am
Posts: 488
Location: Seatlle, WA, USA
Hello neilbaldwin,

I also use ca65 / ld65 for my nes game development. While I don't have the same routine in multiple ROM banks at the same address, I do have fixed locations for all of my ZP (and non ZP) global variables. (ps- I'm using a MMC1 based design).

I don't know if the source to my project would help you or not, but you (or anyone else) are free to look at it. Of particular interest for this thread would be "src/kernel/globals.s" and "src/include/globals.inc".

https://svn.ecoligames.com/svn/nes-game/trunk


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 7:05 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
neilbaldwin wrote:
All of my ZP/RAM vars are defined in one .h file and so I now need to .export everything so the other 'modules' can use the vars.

The typical pattern in C is to "define" the variables (reserve space for them) in a single .c file and "extern declare" them in a .h file that .c files include:
Code:
/* stuff.h */
extern unsigned short foo;
extern unsigned char bar[128];

/* stuff.c */
#include "stuff.h"
unsigned short foo;
unsigned char bar[128];

This works in ca65 too, as the cc65 system has pretty much the same linkage model as C, apart from the difference between 1-byte and 2-byte pointers:
Code:
; stuff.h
.globalzp foo
.global bar

; stuff.s
.include "stuff.h"
.segment "ZEROPAGE"
foo: .res 2
.segment "BSS"
bar: .res 128


Quote:
The only option seems to be to .export every variable and then .import the definitions (or use the auto-import switch for ld65?) but as I've got about 600 variables defined, if there's a less labour-intestive way to avoid having to change the whole .h to to export everything

If you know sed, you can write a one-liner to extract a list of variables and prepend .global or .globalzp as needed. If you don't, you can do the same thing using the regular expression support built into Perl or Python.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 12:29 pm 
Offline
User avatar

Joined: Tue Apr 28, 2009 4:12 am
Posts: 469
Groan....

So, I've type ".export" at the front of all my variables and now I'm using the corresponding ".import" in another file to access them but I seem to be getting a lot of "range errors" e.g

cpx #keyBufferEnd-keyBufferStart

where keyBufferStart and keyBufferEnd are addresses in main RAM.

I'm guessing the resulting arithmetic operation is returning a number that exceeds 8bits but how do I know and more importantly, how do I force it to be correct?

Pllllllease don't tell me I've wasted about 3 hours today trying to make this work :S


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 12:34 pm 
Offline
User avatar

Joined: Sun Sep 07, 2008 7:27 am
Posts: 488
Location: Seatlle, WA, USA
neilbaldwin wrote:
Groan....

Pllllllease don't tell me I've wasted about 3 hours today trying to make this work :S


No matter what solution you choose, you have not wasted 3 hours. At best you've used 3 hours to solve your problem. At worse you've used three hours to learn something :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 2:54 pm 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3471
Location: Indianapolis
Maybe you could try cpx #<(keyBufferEnd-keyBufferStart) to force the lower 8 bits. What a pain, though.

edit - I think I remember doing something like this by putting the duplicated data inside a .scope, but with another label before it (outside the scope) to reference the thing.

But I've done all sorts of weird things with LD65 to get around this sort of stuff, inserting the duplicate data is easy once everything is just anonymous binary data. I think this can be done in the linker, you can make a segment and just output it to the file multiple times. Segment sizes have to be adjusted manually, though.

I didn't know that for a while with LD65 (I guess because 32kB was usually plenty), that having everything output to the same file will simply build up the entire file in the order you link it.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 3:34 pm 
Offline
User avatar

Joined: Tue Apr 28, 2009 4:12 am
Posts: 469
Memblers wrote:
Maybe you could try cpx #<(keyBufferEnd-keyBufferStart) to force the lower 8 bits. What a pain, though.

edit - I think I remember doing something like this by putting the duplicated data inside a .scope, but with another label before it (outside the scope) to reference the thing.

But I've done all sorts of weird things with LD65 to get around this sort of stuff, inserting the duplicate data is easy once everything is just anonymous binary data. I think this can be done in the linker, you can make a segment and just output it to the file multiple times. Segment sizes have to be adjusted manually, though.

I didn't know that for a while with LD65 (I guess because 32kB was usually plenty), that having everything output to the same file will simply build up the entire file in the order you link it.


Yeah, I fixed that cpx just like that. Horrible though.

I managed to get the ROM to build but now it doesn't run (black screen).

Something is wrong somewhere but jesus, it could be anything at this stage :(


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 4:38 pm 
Offline

Joined: Sun Sep 19, 2004 11:07 pm
Posts: 154
I usually just used .global and .globalzp, rather than import/export.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 5:57 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1517
Location: Fukuoka, Japan
Like mentioned above, every new trial will bring some experience in the end so I wouldn't see it as a waste of time. If that was the case, I would be crying a lot over all the re-factoring I did recently ;)

But right now, the problem is maybe you changed too much thing without knowing the impact of that change. In assembler, this can sometime be lethal (I experienced it many time ;;^_^). My suggestion, although abstract, would be that you first roll back to a previous version that work and do the operation on a few variables that you know would have a visual impact right away if they're not working properly. During that phase, don't focus on the code sharing but on the variable sharing only, which seem to be the one causing issue. Once you figure out the cause, you can reproduce the same thing with another group of variable. You should do it gradually since maybe you did some miss (typo or something) and now you cannot figure out where it is. Save every interim revision until the end, just in case something goes wrong during the process.

I had a few issue like that when converting the FT driver. I was doing it in one shot and couldn't figure out where did I miss. Doing it gradually should help.

It may not be the answer that you're looking for but maybe the process could help in the end figuring out what went wrong.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 8:16 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Here's a doc and example code I came up with that cleanly solves what I understand to be the problem: ca65_duped_bank_data.zip


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 31, 2010 11:03 pm 
Offline
User avatar

Joined: Tue Apr 28, 2009 4:12 am
Posts: 469
It's always something stupid isn't it....

In all the code reorganising I'd put the audio engine in the wrong bank so the CPU was executing garbage instead of initialising the APU :)

Well at least it seems to work now, even though my code now looks like a china shop in the wake of a visit by Mr Bull.

Oh and blargg's last post is a really nice elegant solution so after all my .export/.import typing, I'm probably going to scrap it and do it his way.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: cpow, gauauu and 9 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