tschak909 Posted August 10, 2014 Author Share Posted August 10, 2014 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 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 10, 2014 Author Share Posted August 10, 2014 and I spoke too soon, broke the config file loading process slightly. Gonna debug that, and then move forward grrr. -THom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 10, 2014 Author Share Posted August 10, 2014 ...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 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 11, 2014 Author Share Posted August 11, 2014 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 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 12, 2014 Author Share Posted August 12, 2014 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 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 12, 2014 Author Share Posted August 12, 2014 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.org/wiki/Cdb_(software) thoughts anyone? -Thom 1 Quote Link to comment Share on other sites More sharing options...
TXG/MNX Posted August 12, 2014 Share Posted August 12, 2014 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 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 12, 2014 Author Share Posted August 12, 2014 I _am_ storing and looking it up on disk, just trying to minimize the amount of reads needed. -Thom 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 13, 2014 Author Share Posted August 13, 2014 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 1 Quote Link to comment Share on other sites More sharing options...
Android8675 Posted August 13, 2014 Share Posted August 13, 2014 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. 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 13, 2014 Author Share Posted August 13, 2014 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 Quote Link to comment Share on other sites More sharing options...
TXG/MNX Posted August 13, 2014 Share Posted August 13, 2014 Why do you need to close files you can keep several open I think with different channels Quote Link to comment Share on other sites More sharing options...
TXG/MNX Posted August 13, 2014 Share Posted August 13, 2014 Why do you need to close files you can keep several open I think with different channels Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 13, 2014 Author Share Posted August 13, 2014 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 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 14, 2014 Author Share Posted August 14, 2014 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 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 14, 2014 Author Share Posted August 14, 2014 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/tschak909/ataribbs/blob/master/user/src/user.c https://github.com/tschak909/ataribbs/blob/master/user/src/user.h This is me as a result of this bug: http://themortgagenerd.net/wp-content/uploads/2011/06/bigstock_Man_Screaming_In_Pain_And_Agon_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 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 14, 2014 Author Share Posted August 14, 2014 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. 2 Quote Link to comment Share on other sites More sharing options...
danwinslow Posted August 14, 2014 Share Posted August 14, 2014 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. 2 Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted August 16, 2014 Share Posted August 16, 2014 (edited) 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 August 16, 2014 by Shawn Jefferson 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 16, 2014 Author Share Posted August 16, 2014 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 Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted August 16, 2014 Share Posted August 16, 2014 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. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 16, 2014 Author Share Posted August 16, 2014 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 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 17, 2014 Author Share Posted August 17, 2014 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 bbs.zip Quote Link to comment Share on other sites More sharing options...
pixelmischief Posted August 17, 2014 Share Posted August 17, 2014 (edited) @tschak909: What is that background music in your earlier video? And what would you call that genre? Very nice. Edited August 17, 2014 by pixelmischief Quote Link to comment Share on other sites More sharing options...
tschak909 Posted August 17, 2014 Author Share Posted August 17, 2014 @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 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.