Jump to content

Photo

New Atari BBS software.

bbs software cc65 github

390 replies to this topic

#101 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Sat Aug 9, 2014 11:02 PM

To expand on the thought process:

I need to be able to load modules into memory to provide the various BBS functions.

As it turns out, CC65's linker can do a LOT of funky, flexible things in this department, making files that are of any shape, size, file format imaginable.

And if I play my cards right, and define a clean enough API, this means that anyone will be able to make a new cc65 project that can be a module for this BBS.

Since I don't have the foggiest clue on how to do this well, I'm just going to have to play around, until I come up with something that's sane.

The overlay examples that I posted above, depend on a linker config that generates overlay files.

Here's the standard Atari linker config:

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 = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
    TRAILER:       file = %O,               start = $0000, size = $0006;
}
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;
}
Versus, an example config for having up to 10 "overlay" segments:

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__;
}
Oh, but this gets even more interesting, there are memory profiles which allow for the use of OSRAM:

FEATURES {
    STARTADDRESS: default = $2400;
}

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;
}

MEMORY {
    ZP:            file = "", define = yes, start = $0082,                  size = $007E;

# 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;

# "shadow RAM preparation" load chunk
    SRPREPHDR:     file = %O,               start = $0000,                  size = $0004;
    SRPREPCHNK:    file = %O, define = yes, start = %S + __OVERLAYSIZE__,   size = $7C20 - %S - __OVERLAYSIZE__ - $07FF;  # $07FF: space for temp. chargen buffer, 1K aligned
    SRPREPTRL:     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__ +
                                                    __LOWBSS_SIZE__,        size = $D000 -
                                                                                   __STACKSIZE__ -
                                                                                   %S -
                                                                                   __OVERLAYSIZE__ -
                                                                                   __LOWBSS_SIZE__;

# defines entry point into program
    TRAILER:       file = %O,               start = $0000, size = $0006;

# memory beneath the ROM preceeding the character generator
    HIDDEN_RAM2:   file = "", define = yes, start = $D800, size = $0800;

# address of relocated character generator (same addess as ROM version)
    CHARGEN:       file = "", define = yes, start = $E000, size = $0400;

# memory beneath the ROM
    HIDDEN_RAM:    file = "", define = yes, start = $E400, size = $FFFA - $E400;

# overlays
    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;

    SRPREPHDR:   load = SRPREPHDR,                     type = ro;
    LOWBSS:      load = SRPREPCHNK,                    type = bss, define = yes;  # shared btw. SRPREPCHNK and RAM, not zero initialized
    SRPREP:      load = SRPREPCHNK,                    type = rw,  define = yes;
    SHADOW_RAM:  load = SRPREPCHNK, run = HIDDEN_RAM,  type = rw,  define = yes, optional = yes;
    SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw,  define = yes, optional = yes;
    SRPREPTRL:   load = SRPREPTRL,                     type = ro;

    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__;
}
Notice in this one, the memory under the OS ram is presented, along with a few little switches passed into the runtime library to relocate the font out of the system area...

The flexibility is amazing, but it is making my head spin...

In the end, my target is literally a 1088K RAMBO XL, where I want to be able to load overlays into for various system functions. I know i'll get there, it's just going to take some serious experimentation and learning. whee. :) Why don't I ever pick easy things to do? ;)

-Thom

#102 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Sat Aug 9, 2014 11:30 PM

and I spoke too soon, broke the config file loading process slightly. Gonna debug that, and then move forward :P grrr. :)

-THom

#103 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Sun Aug 10, 2014 2:49 PM

...and Fixed. I peeled away the union from the config typedefs that I was using to serialize the bitfields...

Turns out it really wasn't needed and was just overcomplicating things. Config file saving and subsequent reloading works, once again.

Now I'm going to start experimenting with BBS functionality. First up, a user module.

-Thom

#104 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Sun Aug 10, 2014 7:31 PM

Hmm.. Am finding myself needing to come up with a set of routines for a key/value database, particularly for user storage.

I am trying to think on how best to implement something that wouldn't be a total dog on the 6502, would using a 16 bit CRC as a hash of the user id work effectively, as an index?

How would any of you do it?

-Thom

#105 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Mon Aug 11, 2014 11:51 PM

Status report:

I have committed a new 'user' module, where I am developing code to do the user database and its lookups...

The 16 bit CRC seems to work ok as a hash.

For now, When a new user is added, a corresponding user index record is added, which is essentially a pair of values: a hash generated by the username, and a 32-bit value meaning the byte offset within the file.

The byte level seek is only supported by SpartaDOS, but it is very much needed for this.

On a user lookup, the index is read sequentially until a matching hash is found. Then the dat file is read from offset. At some point, I will want to optimize this...a B tree lookup here? hmm not sure... but for now, this should work, once i've debugged the lookup code.

Onward...

-Thom

#106 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Tue Aug 12, 2014 8:26 AM

This looks interesting. Dan J. Bernstein has a hash function for key/value databases that claims to have a constant O(1) lookup time, that _might_ be small enough to cram into cc65:

http://cr.yp.to/cdb/cdb.txt
http://en.wikipedia..../Cdb_(software)

thoughts anyone?

-Thom

#107 TXG/MNX OFFLINE  

TXG/MNX

    River Patroller

  • 3,637 posts

Posted Tue Aug 12, 2014 2:14 PM

Why ram why not look inside a user.dat on disk and only read the needed data. With todays hardware like hdd or sd data read is very quick

#108 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Tue Aug 12, 2014 2:42 PM

I _am_ storing and looking it up on disk, just trying to minimize the amount of reads needed.

-Thom

#109 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Wed Aug 13, 2014 9:51 AM

New Status report, The user module is starting to breathe, I can add users, and look them up. Still need to add an update function.

The algorithm at moment is very simple, a linearly accessed index containing a hash of the username and the 32-bit file offset. The index is read sequentially and matched against calculated hash. If a match is found, the dat file is seeked, and the record returned. Nothing special yet.

But I've made a video taking you into it, and the code.

Sorry, I made this at 2am in the morning, I was half asleep..so.. ;)



Enjoy, more to come,
-Thom

#110 Android8675 OFFLINE  

Android8675

    Moonsweeper

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

Posted Wed Aug 13, 2014 12:12 PM

Looking so good, I'll probably git whatever you got tonight and look around your code for fun. Wish I could offer more, but I think I'm just gonna enjoy the ride until the main structure is complete and I can take a stab at coding my own module.



#111 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Wed Aug 13, 2014 12:15 PM

I am getting _very_ concerned that I am already running into memory issues.

I can't run the current BBS core under SpartaDOS X, for one reason or another, I need to figure out why.

Also, I am having issues with repeated opening and closing of files with the fopen/close/read/write commands. This is becoming quite maddening.

But I forge on...

-Thom

#112 TXG/MNX OFFLINE  

TXG/MNX

    River Patroller

  • 3,637 posts

Posted Wed Aug 13, 2014 12:55 PM

Why do you need to close files you can keep several open I think with different channels

#113 TXG/MNX OFFLINE  

TXG/MNX

    River Patroller

  • 3,637 posts

Posted Wed Aug 13, 2014 12:55 PM

Why do you need to close files you can keep several open I think with different channels

#114 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Wed Aug 13, 2014 1:11 PM

There are only 8 IOCB's in the entire system:

(1) is used by the keyboard/screen (editor)
(1) is used by the printer

and I am trying to conserve the rest, as best as I can. Certain files only need to be open for a moment, to look up information, and shouldn't have their IOCBs being held.

-Thom

#115 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Wed Aug 13, 2014 8:14 PM

Hey guys, have posted this in a few other places including cc65 list, but I figured i'd put it here, too...

I'm thinking through a particular problem that I will eventually need to solve.

I want people to have the ability to implement loadable modules for my BBS engine. They shouldn't need to have to build the code with the knowledge that particular modules will be used in a specific order. Maybe this is possible, maybe it isn't...but....

Based on what I see with the overlay and multi demos, you can indeed specify different code and variable segments be written out into seperate files and/or memory spaces, a consequence of the flexibility of the linker...

Could we have a situation where you could spit out executables that load themselves into a bank of extended memory e.g. on the Atari there is a 16KB window set aside for bank switching in the most common extended memory configuration (the second PIA does the requisite bank switching), and loading an executable would load itself into high memory, and leave a little chunk of memory just below MEMHI as a sort of vector table that the main engine and other modules can bolt onto to call functions?

The idea would be to have a known API that anything could include and call for functions like:

user_get()
last_menu_selection()

etc...

These would be abstract functions that the different modules (a user module, a menu module, a display module, a message board module) would implement, and could be swapped out for other modules, while still adhering to this basic framework, this would allow for a certain amount of modularity and flexibility when building a BBS.

In the end, I don't care if it's an executable (it would be nice, as e.g. a SpartaDOS batch file would load the requisite modules in place, and start the BBS), or if its some sort of binary blob that gets loaded into place, I'm just trying to think of a way forward, after I write all these little functions to be able to have a parser read through a map of the BBS and load/unload/reload specific modules in response to things happening...

-Thom

#116 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Wed Aug 13, 2014 10:03 PM

I have sent the following to the cc65 list:

Ok guys,

I am at the end...of my fucking rope...

I have managed to side-step this for weeks now, but I need to either
figure out if:

(1) this is a problem I am doing, not using something correctly, OR
(2) this is a problem that someone (myself included) needs to fix in
the standard libs for atari.

If I use fopen and fclose enough times, I eventually get an EMFILE
error. No way around it, I've written several pieces of different code
that exhibit this behavior.

I am working on functions for a user database for a BBS, and it has a
test harness that is failing.

The error is shown here: http://i.imgur.com/z4lvizT.png

The code is here:
https://github.com/t...user/src/user.c
https://github.com/t...user/src/user.h

This is me as a result of this bug:
http://themortgagene...gon_2270461.jpg


The files it is accessing are:

* NUMUSERS, a simple counter.
* USER.DAT, the user database
* USER.IDX, the index file.

Once any of these files are done being used, I fclose them. I am
trying to conserve IOCBs as much as I can, because they are so few on
the Atari.

Can anyone help?

Thanks,
-Thom

#117 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Thu Aug 14, 2014 12:06 AM

A breakthrough.

 

On a whim, I wrote a test program using the POSIX calls (open/read/write/close) as opposed to the ANSI C (fopen/fread/fwrite/fclose) calls. The program was able to open and close a test file 255 times, writing to it in the middle of that process.

 

So I changed the user code entirely to use the POSIX calls, and what do you know? It passes now. 

.

The moral here? The ANSI C file operations are BUH_ROKEN, as far as the atari target, is concerned. I will no longer use them, as they in the end just call the underlying functions I am now using, anyway. Basically it seems the f* functions don't take the reference counting in findfreeiocb and friends into account...

 

Moving on, now. But first...BED.

 

Rtp0iwT.png



#118 danwinslow OFFLINE  

danwinslow

    River Patroller

  • 2,591 posts

Posted Thu Aug 14, 2014 7:08 AM

CC65 is a very good compiler, its unusual  to find significant issues but you may have found one. IT's very good at compiling ANSI C but the mapping of the standard libraries to target machines sometimes need some work. You could always investigate the library in question yourself, and suggest fixes. You can get the source code for the entire system, do your own fixes, and then send them patches for approval.

 

You will probably run into memory issues if you write the entire thing in C. You should adjust your linker config to maximize memory, there's some simple things you can do. For instance, cut your parameter stack down from 2k, the default is way too large. Stay away from large complicated structs and stuff like that, its best to have everything flat and to prefer arrays of scalars over arrays of structs. Keep your function parameters down to a minimum. Use a lot of globals. Consider linking as little of the libraries as possible, and writing your own calls to SIO and CIO. For instance, using the FILE * stuff is a 9k hit, and you can write your own specialized stuff in much less. Learn to use the embedded assembly capability, you will gain speed and save memory. When I write a large program in CC65, I usually wind up using the C language as just kind of a structural glue around a lot of embedded assembler.

 

You can use extended memory banks to hold code and data. You will probably have to mostly roll your own ability to do that...it's not particularly hard once you figure out a calling and parameter passing methodology. It usually involves copying things a bit back and forth. CC65 does have some libraries to do extended memory, but I'm not sure what the status on that is for the Atari target, last time I looked at it it wasn't viable, but that was a while ago. Don't forget you can swap out the OS on some machines, too. I would also get a second emulator running, say the atariwin800 one, so that you can weed out things that are problems of the emulators rather than actual problems in your code.



#119 Shawn Jefferson OFFLINE  

Shawn Jefferson

    Stargunner

  • 1,987 posts
  • Location:Victoria, Canada

Posted Fri Aug 15, 2014 10:24 PM

The moral here? The ANSI C file operations are BUH_ROKEN, as far as the atari target, is concerned. I will no longer use them, as they in the end just call the underlying functions I am now using, anyway. Basically it seems the f* functions don't take the reference counting in findfreeiocb and friends into account...


I can't reproduce your problem here. I have a test program that opens a file, writes to it, closes it, five different file names. Then it read each file, prints the contents and closes the file. It runs this forever... no crashes, no problems, all the data is read fine.

Is the problem having multiple files open at the same time? IOCB reuse doesn't seem to be an issue, at least with the version of cc65 and Atari runtime I'm on.

Test code I ran:
 
#include <atari.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>

char r_data[80];
char w_data[80];


int main()
{
  FILE *fp;
  unsigned char f;
  int i;

  i = 0;

  while(1) {
    i = i + 1;
    for(f=0;f<6;++f) {
      sprintf(w_data, "fp%d: %d", f, i);
      printf("%s\n", w_data);

      sprintf(r_data, "d:test%d.dat", f);
      fp = fopen(r_data, "wb"); 
      if (!fp) return(0);
      fwrite(&w_data, 80, 1, fp); 
      fclose(fp);
    }

    fflush(fp);

    strcpy(w_data, "");
    strcpy(r_data, "");

    for(f=0;f<6;++f) {
      sprintf(w_data, "d:test%d.dat", f);
      fp = fopen(w_data, "rb"); 
      if (!fp) return(0);
      fread(&r_data, 80, 1, fp); 
      printf("%s\n", r_data);
      fclose(fp);
    }
  }

  return(0);
}
note: that fflush is probably redundant, I edited a test program I already had.

PS. This program only compiles to slightly over 5k, not 9k, but the file functions and the heap memory allocation functions definitely will eat up some ram. Get the linker to generate a map file, and you can see how much space each module is using, and your overall segment RAM use too. printf and friends take quite a lot of RAM too.

Edited by Shawn Jefferson, Fri Aug 15, 2014 10:51 PM.


#120 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Fri Aug 15, 2014 10:42 PM

I can't reproduce your problem here. I have a test program that opens a file, writes to it, closes it, five different file names. Then it read each file, prints the contents and closes the file. It runs this forever... no crashes, no problems, all the data is read fine.

Is the problem having multiple files open at the same time? IOCB reuse doesn't seem to be an issue, at least with the version of cc65 and Atari runtime I'm on.

Test code I ran:
 

#include <atari.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>

char r_data[80];
char w_data[80];


int main()
{
  FILE *fp;
  unsigned char f;
  int i;

  i = 0;

  while(1) {
    i = i + 1;
    for(f=0;f<6;++f) {
      sprintf(w_data, "fp%d: %d", f, i);
      printf("%s\n", w_data);

      sprintf(r_data, "d:test%d.dat", f);
      fp = fopen(r_data, "wb"); 
      if (!fp) return(0);
      fwrite(&w_data, 80, 1, fp); 
      fclose(fp);
    }

    fflush(fp);

    strcpy(w_data, "");
    strcpy(r_data, "");

    for(f=0;f<6;++f) {
      sprintf(w_data, "d:test%d.dat", f);
      fp = fopen(w_data, "rb"); 
      if (!fp) return(0);
      fread(&r_data, 80, 1, fp); 
      printf("%s\n", r_data);
      fclose(fp);
    }
  }

  return(0);
}
note: that fflush is probably redundant, I edited a test program I already had.

 

No sooner you said that, than I've run into the problem here.. It's something in my code, I'll find it.

 

In the mean time, I'm working on the user code, and making it as atomic as I possibly can (I try not to hold onto any file descriptors for any longer than I need them.) 

 

I'm going to have to be very lean with my error checking, as it seems me checking each and every file operation adds quite a bit to the resulting binary...

 

My end goal with anything that works with database files is to:

 

(1) make a temporary copy

(2) open

(3) do file operation

(4) close

(5) move temporary copy over original.

 

Yes, it will slow things down, but it will ensure against corruption of the database, and a requirement of this BBS is that it be run on a HARD DRIVE (or some emulated facsimile of one). 

 

-Thom



#121 Shawn Jefferson OFFLINE  

Shawn Jefferson

    Stargunner

  • 1,987 posts
  • Location:Victoria, Canada

Posted Fri Aug 15, 2014 10:57 PM

Glad you are tracking it down, and it doesn't seem to be a problem in the library.

Did you see my message on the cc65 mailing list about modules? I should have just responded here, but I saw it there first.

#122 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Fri Aug 15, 2014 11:55 PM

Glad you are tracking it down, and it doesn't seem to be a problem in the library.

Did you see my message on the cc65 mailing list about modules? I should have just responded here, but I saw it there first.

 

Yeah, I did.. It's going to take me a lot of experimenting and stumbling around to find a workable solution.

 

What I'm hoping is that I can have the lion's share of the core in main memory, linking back to standard libs/whatever, and have the different overlays only call functions that are in the main program... I dunno...maybe each overlay blob plops a pointer to a struct of function pointers in main memory...

 

Still thinking... slowly going insane... :)

 

p.s. Shawn, have you looked @ at my code?:

 

http://github.com/tschak909/ataribbs/

 

-Thom



#123 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Sat Aug 16, 2014 10:45 PM

Ok guys, I need some help. Have really hit a wall.
 
Can somebody run this binary through debugger emulation under SpartaDOS X and help me figure out why the hell this thing is failing to load? It works perfectly under SD3.2, but it doesn't load under SDX, with either OSRAM or BANKED. I'm _really_ confused.
 
-Thom

Attached Files

  • Attached File  bbs.zip   39.35KB   105 downloads


#124 pixelmischief OFFLINE  

pixelmischief

    Stargunner

  • 1,288 posts

Posted Sat Aug 16, 2014 11:30 PM

@tschak909: What is that background music in your earlier video? And what would you call that genre? Very nice.

Edited by pixelmischief, Sat Aug 16, 2014 11:30 PM.


#125 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,242 posts
  • Location:USA

Posted Sat Aug 16, 2014 11:55 PM

@tschak909: What is that background music in your earlier video? And what would you call that genre? Very nice.

 

Essay - "A Cold Day" ... from Bleep.com's top 100 of 2012.

 

The genre is best described as cryo-ambient. 

 

-Thom







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