Hi, as memory is always a very precious resource on the Apple2 I'd like to shed some light on the memory management side of file io... The Apple2 has lower memory from $0000 to $BFFF (48 k). At least for text mode programs $0800 to $BFFF (46 k) is available. Then there is a memory mapped io area from $C000 to $CFFF (4 k). From $D000 to $FFFF (12 k) we have upper memory. 1. scenario: DOS 3.3 DOS 3.3 normally occupies $9600 to $BFFF (10,5 k). This includes buffers for the default of three concurrently opened files. Reducing this to one file ("MAXFILES 1") results in $9AA6 to $BFFF (9,3 k). A program calling DOS 3.3 may reuse those buffers or supply memory for file i/o on its own. I'd opt for supplying own buffers for two reasons: - The maximum number of concurrently opend files is dynamic. - In scenario 2. described below reuse of buffers is very difficult. If the calling program doesn't reuse DOS 3.3 buffers it can destroy them all after loading and rebuild them on exit. Without any buffers DOS 3.3 uses $9D00-$BFFF (8,7 k). 2. scenario: DOS 3.3 in upper memory Several DOS 3.3 variants may be moved into upper memory. There they occupy all of the upper memory (12 k) and a little amount of lower memory from $BF00 to $BFFF (0,25 k) or $BE00 to $BFFF (0,5 k). The number of buffers of concurrently opend files is typically fixed to five. Unfortunately there's no "official" standard for accessing the buffers so a program is better off supplying its own buffers. Results for DOS 3.3 Sceanrio 1. gives an text mode application a total of 49,2 k (37,2 k + 12 k) memory but unfortunately the current cc65 linker isn't able to span a segment accross several memory areas. Therefore it's impossible to make use of the upper memory in a generic way. Therefore we have to stick to scenario 2. with ~ 45,6 k of _CONTIGIOUS_ memory left for the application. BTW: This does _NOT_ mean that we become incompatible scenario 1. It just means that a memory intensive application won't use it. Pro's: - No special startup/cleanup code - Bank switching to ROM is done by moved DOS 3.3 Con's: - ~ 3,6 k less memory - User needs movable DOS 3.3 (not too popular) 3. scenario: ProDOS 8 with command interpreter The ProDOS 8 kernel uses the same memory as DOS 3.3 being moved into upper memory: The whole upper memory (12 k) plus $BF00 to $BFFF (0,25 k) of lower memory. The ProDOS 8 command interpreter additionally occupies $9600 to $BEFF (10,2 k). These values don't include any buffers so they have always to be provided by the application. A word on these buffers: While a DOS 3.3 file buffer occupies only 557 bytes a ProDOS 8 file buffer needs 1024 bytes of memory _ALIGNED_TO_A_PAGE BOUNDARY_. Assuming that file buffers are allocated on the cc65 heap and that there is no "aligned malloc" this makes up 1024 + 255 = 1279 bytes per file buffer ! @Jim: Do you agree with this or did I miss a point? @Ullrich: Do you see an option to provide some memory allocation mechanism suitable for ProDOS 8 file buffers? This scenario is compatible with DOS 3.3 for all application that don't do file i/o themselves. This means that: - The application binary is loaded directly to its target location (typically $0800 for text mode programs) - The application simply quits with a JMP to DOS (which means the command interpreter for ProDOS 8) 4. scenario: ProDOS 8 without command interpreter The assembly language file io APIs of ProDOS 8 are part of the ProDOS 8 kernel thus there is no need for the command interpreter to be present while an application is running. In fact all "profesional" ProDOS 8 programs use this scenario. Unfortunately - but not surprisingly - this doesn't come for free: - The application binary is always loaded at $2000. The application has basically two options a) move the loaded binary to its target location or b) provide a small loader to load the "real" binary directly to the target location using the file i/o API. - The application has to call a special quit API on exit. The called quit routine will then allow the user to load the next application (for example the command interpreter). Results for ProDOS 8 As scenario 3. leaves only 35,5 k for a text mode program it is desirable to support scenario 4. with 45,7 k of available memory. For applications with large amounts of CODE + RODATA + DATA (in other words a large binary file) it may simply be impossible to load the file at $2000. Therefore the approach with a small loader seems to be appropriate. The major part of this loader could be written in C and use the new file io library to load the main binary at $0800 and jump to it. It would have a custom startup code relocating the loader from $2000 to let's say $B000. This area would then wiped out later by the BSS, heap or stack of the main executable. The loader would be identical for all cc65 applications and just have a different name. ProDOS 8 supports "argv[0]" so the loader could detect from that the path of the main binary with a pattern like MYAPP.SYSTEM for the loader and MYAPP.BINARY for the main binary. A benefit of this approach would be that the startup code for DOS 3.3 binaries and ProDOS 8 main binaries could be shared. Just the last call at the very end of the startup code would have to go into the file i/o libraries instead of being hardcoded in crt0.s. A destructor which never returns doesn't look like a clean solution - does it? Setting up a RESET handler for closing files (as requested by the ProDOS 8 tech ref manual) could be done from a constructor in the ProDOS 8 file i/o library. This handler would call exit() after doing its job. Or we decide that we generally (for all kind of Apple2 binaries) want a RESET handler only calling exit(). Then the ProDOS 8 file i/o library would just need an atexit() hook... Oliver ---------------------------------------------------------------------- To unsubscribe from the list send mail to majordomo@musoftware.de with the string "unsubscribe cc65" in the body(!) of the mail.Received on Fri Jul 30 00:25:50 2004
This archive was generated by hypermail 2.1.8 : 2004-07-30 00:25:59 CEST