tschak909 Posted September 30, 2014 Author Share Posted September 30, 2014 I need to test on a real one. -Thom Quote Link to comment Share on other sites More sharing options...
danwinslow Posted September 30, 2014 Share Posted September 30, 2014 (edited) The linker configuration has changed significantly with the newest builds of cc65, am going to have to piece together something between danwinslow's example and the cc65 overlay example: FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __EXEHDR__: type = import; __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # file header, just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; RAM: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $BC20 - __OVERLAYSIZE__ - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; TRAILER: file = %O, start = $0000, size = $0006; OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__; OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__; OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__; OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__; OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__; OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__; OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__; OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__; OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__; } SEGMENTS { EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = RAM, type = ro, define = yes; LOWCODE: load = RAM, type = ro, define = yes, optional = yes; INIT: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; AUTOSTRT: load = TRAILER, type = ro; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = INIT; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } It must be the stress of my day job, or i'm burning out, but am having trouble understanding how the different segments fit together and which ones are needed at a minimum for an atari binary. (e.g. I know I need at least the header, and one segment with a run and/or init address pointer...but what does CC65 need for its own housekeeping on top of that?) -Thom Well, I'm not familiar with the latest changes in the linker formats, but it looks like the overlay stuff is not actually setting up to use ext memory, its just defining a 4k block at $2000 into which you can load code. Seems like a fine idea to me, if you can live with the IO between modules. It leaves everything else pretty much in place, meaning all your data and so forth. It's basically what I did with the LOWCODE segment in my example. Its kind of a small overlay space though...the overlays would have to be very self contained, and only call functions that are not overlays themselves. I would think you could combine it with using ext banks, but you'd have to design the various chunks thoughtfully.You'd need some kind of an overlay loader, but that would be a simple task. Of course you could always just not use the overlays and go with regular ext banking. What CC65 needs is the startup code from crt0.s, the stack, the C library code, all not banked or overlaid. Actually you could probably bank the startup code if you really wanted to but it wouldn't be worth it. I have no idea what the SYSCHK stuff is all about. Edited September 30, 2014 by danwinslow Quote Link to comment Share on other sites More sharing options...
drac030 Posted September 30, 2014 Share Posted September 30, 2014 Ok, so there's a late binding facility to look up symbols. Very cool. Thanks Drac030. So it sounds like, technically at least, one can look up the malloc/free routines from a non-relocatable binary, provided that the cartridge is not disabled. Yes. In fact, it is not relevant, if the library is enabled or not: in the latter case, the jfsymbol call will enable the library, do the search, and disable the library. The only inconvenience is a glitch in the screen, if the screen RAM and DL are located "under" the cartridge ($a000-$bfff). I imagine, even if the cart was disabled, you could write a wrapper that would enable it and make the call, and the disable it again, which is what you were referring to when you said 'or the access becomes complicated'. Yes. There is a kernel call which centralizes cartridge management (and makes it hardware abstracted, so that you do not have to worry what type of a cartridge the SDX is running on). You use it to enable the cartridge, when it is disabled, or disable it when it is enabled (this is obviously exactly the thing X.COM does). The only problem is the screen, the program wishing to manipulate the cartridge state must take care of the screen memory. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted October 1, 2014 Share Posted October 1, 2014 (edited) Maybe this will help you?http://cc65.github.io/cc65/doc/atari.html#ss11.4Hmm, that's actually pretty old. Here's a quick example I whipped up: FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __EXEHDR__: type = import; #__SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # file header, just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; RAM: file = %O, define = yes, start = %S, size = $4000 - %S, fill = yes; BANK0: file = %O, define = yes, start = $4000, size = $4000, fill = yes; RAMHI: file = %O, define = yes, start = $8000, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - $8000; TRAILER: file = %O, start = $0000, size = $0006; BANK1: file = "%O.1", define = yes, start = $4000, size = $4000; BANK2: file = "%O.2", define = yes, start = $4000, size = $4000; } SEGMENTS { EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = RAM, type = ro, define = yes; LOWCODE: load = RAM, type = ro, define = yes, optional = yes; INIT: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro, define = yes; RODATA: load = RAMHI, type = ro; DATA: load = RAMHI, type = rw; BSS: load = RAMHI, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; AUTOSTRT: load = TRAILER, type = ro; BANK0SEG: load = BANK0, type = ro, define = yes; BANK1SEG: load = BANK1, type = ro, define = yes; BANK2SEG: load = BANK2, type = ro, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = INIT; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } #include <stdlib.h> #include <stdio.h> #include <conio.h> void bank0_stuff(void); void main(void) { cprintf("Hello World! This is in main RAM.\n\r"); cgetc(); bank0_stuff(); return; } #pragma code-name("BANK0SEG") #pragma data-name("BANK0SEG") unsigned int bank0_var = 0x0101; void bank0_stuff(void) { cprintf("This is in the main executable, and already loaded to $4000, no banking required.\n\r"); cgetc(); bank0_var = 0x3333; return; } #pragma code-name("BANK1SEG") #pragma data-name("BANK1SEG") unsigned int bank1_var = 0x1111; void bank1_stuff(void) { cprintf("This is in the bank1 file, you must load it into $4000 before jumping here!\n\r"); cgetc(); bank1_var = 0x3333; return; } #pragma code-name("BANK2SEG") #pragma data-name("BANK2SEG") unsigned int bank2_var = 0x2222; void bank2_stuff(void) { cprintf("This is in the bank2 file, you must load it into $4000 before jumping here!\n\r"); cgetc(); bank2_var = 0x3333; return; } This example is a bit contrived... but it shows the basic config file, splitting your "banked" code into different overlay files that you can then load into $4000 before calling. Ideally you would put each banks functions, data and rodata into it's own file (notice I didn't ask to put RODATA into the banks... cc65 by default tries to optimize your rodata, you are better off only using #pragma rodata-name("BLAH") only once in a source file. There is a switch to disable this, but I don't think you want to disable optimizations, just be aware of it!)A few other things to be aware of..- The default crt0.s file defines your C stack (and heap I believe), so be aware of what it's doing for you. I've rewritten crt0.s for some of my projects and just compile my own to have complete control of things like the stack.- If you want to keep a "hole" in your code at $4000 then you need to somehow take account of that in your output file. I've used "fill = yes" to make the executable line up properly in memory when it's loaded in. The config file I linked to above in the cc65 documentation takes another approach.- BSS is cleared by crt0.s, but only the BSS segment. Any BSS you try to put in other places won't get cleared, and you may have to do it yourself.- Use the memory map file, it'll help you figure out what's going where.I hope that helps somewhat. You're going to have to learn the linker config (I'm no expert either), and place your code where you want it, and make sure to keep in mind where things are when calling functions! PS. I commented out the SYSCHECK stuff... if you want it, uncomment it. extbank.zip Edited October 1, 2014 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
danwinslow Posted October 1, 2014 Share Posted October 1, 2014 So, this one puts the startup and C library code in $2000-$4000? I guess the stack and heap would be there too unless you modded crt0.s? Is there enough room? What is the syschk stuff all about? Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted October 1, 2014 Share Posted October 1, 2014 (edited) syschk just checks that your machine has enough memory before loading the rest of the executable (it uses a separate executable segment to load and run first.) The default crt0.s for the Atari (not atarixl) target puts the stack always at the top of memory: 72 sec 73 lda MEMTOP 74 sbc #<__RESERVED_MEMORY__ 75 sta APPMHI ; initialize our APPMHI value 76 sta sp ; set up runtime stack part 1 77 lda MEMTOP+1 78 sbc #>__RESERVED_MEMORY__ 79 sta APPMHI+1 80 sta sp+1 ; set up runtime stack part 2 81The heap, I believe sits just under the stack and runs down to BSS (I left BSS in high memory for that reason, but typically I don't use the heap in cc65, it's too heavy.) 16 __heaporg: 17 .word __BSS_RUN__+__BSS_SIZE__ ; Linker calculates this symbol 18 __heapptr: 19 .word __BSS_RUN__+__BSS_SIZE__ ; Dito 20 __heapend: 21 .word __BSS_RUN__+__BSS_SIZE__ 22 __heapfirst: 23 .word 0 24 __heaplast: 25 .word 0 26 27 28 ; Initialization. Will be called from startup! 29 30 .segment "INIT" 31 32 initheap: 33 sec 34 lda sp 35 sbc #<__STACKSIZE__ 36 sta __heapend 37 lda sp+1 38 sbc #>__STACKSIZE__ 39 sta __heapend+1 40 rts Is there enough room? No, there never is. You have to manage your RAM... It depends on how many library functions you are trying to use. Heap will use a lot of RAM, so will printf, file routines, etc... Edited October 1, 2014 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
danwinslow Posted October 1, 2014 Share Posted October 1, 2014 (edited) Ah yep, the heap and stack would go high with the data segments. wait..what? manage RAM? On this machine? No Way! Well, I meant enough room for all the heap and so forth between $2000-$4000, but I wasn't thinking straight. Edited October 1, 2014 by danwinslow Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 5, 2014 Author Share Posted October 5, 2014 I will be taking a break from BB65 coding, to work on my main project. I need to experiment and think some things over. I will be back, as I do want to finish this thing. -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 11, 2014 Author Share Posted October 11, 2014 BBS is down temporarily. It's not very interesting at this stage, anyway. I'll put it back up once it starts breathing in extended memory. -Thom Quote Link to comment Share on other sites More sharing options...
Kirkman Posted October 21, 2014 Share Posted October 21, 2014 So, I pulled down the Syncterm source and tried to build it. Unfortunately, it looks like there are many compatibility issues with the source and the Xcode 6 libraries I have installed, and I don't have time to try and get a clean version built. I may try building on another Mac (one without Xcode 6) and see if that goes more smoothly. I did track down the code that does the copy/paste, in /src/conio/sdl_con.c: [snip] It looks like there's a 1:1 mapping of the functions, so it should be pretty straightforward to update the code. Also, the app doesn't respond to Cmd-Q to quit, so it would be nice to fix that as well. Al, just wondering if anything ever came of this. --Josh Quote Link to comment Share on other sites More sharing options...
w1k Posted February 12, 2015 Share Posted February 12, 2015 any news? Quote Link to comment Share on other sites More sharing options...
tschak909 Posted February 12, 2015 Author Share Posted February 12, 2015 Life has stepped in, and I had to resume work on my primary project (and work)... I will return to this when I can. In the mean time, code is up at github, for anyone who wants to take it and run with it. -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 8, 2015 Author Share Posted May 8, 2015 Yes, this project is on hold. I managed to accomplish the bits I initially wanted to accomplish, that is, is it possible to do real software development for a 6502 target in C? Yes. I am coming back to the project when i get a concise plan of attack, but I already know that I do not want to load the whole BBS into RAM. There simply is no reason for it, and not worth the added expense. What I am intending to do, is to seperate the BB65 into seperate program modules: * a resident core program, that provides common routines for all the programs, namely MODEM I/O, and simple input field processing for the sake of consistency. * a menu processor, load a menu file, grab an input, exit with an exit code for what was selected. * a message board reader * a message board editor * a file viewer (for bulletins, art, etc.) * etc. Plumbing through exit codes, as needed with probably a batch file. This would keep memory consumption down, and allow the different modules to use memory best for what is needed at that moment. No, it would not be slow. Keep in mind, I am running all of this on a SIDE 2, a hard drive is required for this BBS, full stop, and loading the modules won't slow down interactivity. Some more to think about... -Thom 2 Quote Link to comment Share on other sites More sharing options...
Android8675 Posted May 8, 2015 Share Posted May 8, 2015 So awesome to hear from you again Thom... can't wait to muck around some more. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 8, 2015 Author Share Posted May 8, 2015 I never left this board. I just have a rotating set of projects and things on my long term to-do list, that I work on, until I check them off. -Thom 1 Quote Link to comment Share on other sites More sharing options...
Kirkman Posted October 13, 2015 Share Posted October 13, 2015 So, I pulled down the Syncterm source and tried to build it. Unfortunately, it looks like there are many compatibility issues with the source and the Xcode 6 libraries I have installed, and I don't have time to try and get a clean version built. I may try building on another Mac (one without Xcode 6) and see if that goes more smoothly. I did track down the code that does the copy/paste, in /src/conio/sdl_con.c: [snip] It looks like there's a 1:1 mapping of the functions, so it should be pretty straightforward to update the code. Also, the app doesn't respond to Cmd-Q to quit, so it would be nice to fix that as well. FWIW, Deuce did finally release SyncTerm v1.0 (Mac download link). As part of 1.0, he fixed the broken copy-and-paste on the Mac! So I unequivocally recommend SyncTerm to anyone using a Mac who wants to call BBSes. Tons of great features, including support for ATASCII. --Josh Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.