Jump to content

Photo

New Atari BBS software.

bbs software cc65 github

390 replies to this topic

#376 tschak909 ONLINE  

tschak909

    Stargunner

  • Topic Starter
  • 1,934 posts
  • Location:USA

Posted Mon Sep 29, 2014 10:33 PM

I need to test on a real one.

 

-Thom



#377 danwinslow OFFLINE  

danwinslow

    River Patroller

  • 2,532 posts

Posted Tue Sep 30, 2014 6:58 AM

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 by danwinslow, Tue Sep 30, 2014 7:02 AM.


#378 drac030 OFFLINE  

drac030

    Stargunner

  • 1,833 posts
  • Location:Warszawa, Poland

Posted Tue Sep 30, 2014 7:33 AM

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.

#379 Shawn Jefferson OFFLINE  

Shawn Jefferson

    Stargunner

  • 1,986 posts
  • Location:Victoria, Canada

Posted Tue Sep 30, 2014 8:11 PM

Maybe this will help you?
http://cc65.github.i...ari.html#ss11.4

Hmm, 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.

Attached Files


Edited by Shawn Jefferson, Tue Sep 30, 2014 9:11 PM.


#380 danwinslow OFFLINE  

danwinslow

    River Patroller

  • 2,532 posts

Posted Wed Oct 1, 2014 6:04 AM

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?



#381 Shawn Jefferson OFFLINE  

Shawn Jefferson

    Stargunner

  • 1,986 posts
  • Location:Victoria, Canada

Posted Wed Oct 1, 2014 10:47 AM

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
81
The 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 by Shawn Jefferson, Wed Oct 1, 2014 11:46 AM.


#382 danwinslow OFFLINE  

danwinslow

    River Patroller

  • 2,532 posts

Posted Wed Oct 1, 2014 12:11 PM

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 by danwinslow, Wed Oct 1, 2014 12:13 PM.


#383 tschak909 ONLINE  

tschak909

    Stargunner

  • Topic Starter
  • 1,934 posts
  • Location:USA

Posted Sun Oct 5, 2014 10:46 AM

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



#384 tschak909 ONLINE  

tschak909

    Stargunner

  • Topic Starter
  • 1,934 posts
  • Location:USA

Posted Sat Oct 11, 2014 10:10 AM

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



#385 Kirkman OFFLINE  

Kirkman

    Star Raider

  • 89 posts
  • Location:Ferguson, MO

Posted Tue Oct 21, 2014 2:08 PM

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



#386 w1k OFFLINE  

w1k

    Stargunner

  • 1,660 posts
  • Location:martin, slovakia

Posted Thu Feb 12, 2015 12:30 PM

any news?:)



#387 tschak909 ONLINE  

tschak909

    Stargunner

  • Topic Starter
  • 1,934 posts
  • Location:USA

Posted Thu Feb 12, 2015 12:33 PM

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



#388 tschak909 ONLINE  

tschak909

    Stargunner

  • Topic Starter
  • 1,934 posts
  • Location:USA

Posted Fri May 8, 2015 11:12 AM

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



#389 Android8675 OFFLINE  

Android8675

    Moonsweeper

  • 426 posts
  • Incognito'N
  • Location:Prunedale, CA, USA

Posted Fri May 8, 2015 11:49 AM

So awesome to hear from you again Thom... can't wait to muck around some more.



#390 tschak909 ONLINE  

tschak909

    Stargunner

  • Topic Starter
  • 1,934 posts
  • Location:USA

Posted Fri May 8, 2015 12:10 PM

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



#391 Kirkman OFFLINE  

Kirkman

    Star Raider

  • 89 posts
  • Location:Ferguson, MO

Posted Tue Oct 13, 2015 11:27 AM

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







Also tagged with one or more of these keywords: bbs, software, cc65, github

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users