@L}5 _$% l0$)$$Hȱ$ UhL" `e$$%`$%`  R@P!( L(1   Y I`  d  Ld M * @  $ % CC$$)%1 Udߥ$9%: !0 S$% DD˙`  }J)Lr d M * @  $ % CC$$)%1 Udߥ$9%: !0 S$%} DD˙`  }J)Lr J  ((  p L ()   J}L= ( L 0q A    IB JC;? D W } LL  ` W )LA!  ߰")-݆ p" } $G@LL 08`Q")<2Q0 -G$Ș݆ UL# ; p8(()(0ʥ)NQ` }$GȘ݆LU )L ݆ L GȘ ݆LL )W>Z   HH)H }p h  hyhy D L> L JJ    ! LA*` BF }7'8  M HN H` 8 Z  \LdJJ!"! GFE@F (!L }EE !E^ ^ E E7EȩEdE/EȩE  D } .L }  ;F d  ;?F7F? ( .   Z D LL d } . D  L    p  E` , d)  D L) 0BM݊L݉} ML  N݆ L NLML [ TEqEHȱEqEh 0Gȹ G} HLL GɛL  LFREE SECTORS G) *Gȩ GȽG GȌ*jj >G} C8jJ3j2CD( C202C ԠBX` N 1? l LlD:RAMDISK}.COMLu L1 L ;LHL  T`  `1  ɐ     `TU  } L ? .  t`GBJ ~DEHI B V0dV!}QDEHI VF9 ,0 ,0 s0hhL  L` H hDHEh"}DEL8HI4 0 HI,0 0  9 .G VLO#},0 L4*IJ`llD1:AUTORUN.SYSNEED MEM.SAV TO LOAD THIS FILE.D1:MEM.SAV J y08 B|DEHI$} V0 0`B;DEL`?<0LV`@ʆ v s? F0Ξ05: [ BDEHI%} VY8 B V  @  /DE `E:D1:DUP.SYSERROR-SAVING USER MEMORY ON DISKTYPE Y TO &}STILL RUN DOS B;DE J  (` 9 V⪍ ઍ  -'}LLu ÝDEHILV 9 .l 9 .l  `` s$B BH(}I|DE V BLV nB,DE JLV B V BLVDEIʩ BꭝLu  } 3E:}DISK OPERATING SYSTEM II VERSION COPYRIGHT 1984 ATARI CORP.A. DISK DIRECTORY I. FORMAT DISKB. RUN CARTRIDG*}E J. DUPLICATE DISKC. COPY FILE K. BINARY SAVED. DELETE FILE(S) L. BINARY LOADE. RENAME FILE M. RUN AT ADDRES+}SF. LOCK FILE N. CREATE MEM.SAVG. UNLOCK FILE O. DUPLICATE FILEH. WRITE DOS FILES P. FORMAT SINGLEL !N',}#"&))9(&*)/h)''-&؆莟R'S  vL/ˢ L }Insert DOS 2.0s, type Y Λx -}DEfHI 1莏#q! @ y0ɛ8A0,' ȅ 1 1ild! 1L!NO SUCH ITEMSELECT.} ITEM OR FOR MENU! 0 .z:*{}.|{ 1 0 0JB 18L%|DL/}%DIRECTORY--SEARCH SPEC,LIST FILE?[# 0 0 &|D3" 1L!NOT A DISK FILEN !B 1L!E# 1 !BD0}ED:}:1BJ|DE 1DEBHI 1 h0ߢ 0.1}  0?詛 1 y0YЛ 1 ;#L" ;#L! BL1TYPE "Y" TO DELETE...DELETE FILE SPEC2}COPY--FROM, TO?OPTION NOT ALLOWED736 FREE SECTORS COPYING---D1:DIRECK.COMl# 0|D .L/%#3}##JB|DE 1BHID#E 1#0: B 1L!#͑### B 1#c$0SY4}S1}:## # # .#Ƚ# # 𩛙## 1,#PD#ELJ- <.BJD#E 5}1 1HH 0hh|DL%1}:̳# L% #D#EL% 1 0 . .0O% 1L!WILD CARDS NOT A6}LLOWED IN DESTINATION 0 <.|K}N 2 FORMAT. t* 5) 1L!`) 0NΞ 0 L1) 1 L!BAD LOAD FILELOAD FROM WHAT FILE?) 0 ?}0#B 1L!WHAT FILE TO LOCK?) 0 0$B 1L!WHAT FILE TO UNLOCK?DUP DISK-SOURCE,DEST DRIVES?TYPE "Y" IF OK TO US@}E PROGRAM AREACAUTION: A "Y" INVALIDATES MEM.SAV.FE! +L1   `*  70 2 2A} 0.* 1 y0 0)INSERT BOTH DISKS, TYPE RETURN^, 1 y038逍 N, 1L! ,B}C, t*  Lx+, 0 ^, 1 y0 , ,0,0 ,L+ ,I0 ,Vǭ0C}Ξ, 0 }, 1 y0C,ШC, 0K'!" H H 'h h Lx+!EF 5L1L!D,I,HhD}` NOT ENOUGH ROOMINSERT SOURCE DISK,TYPE RETURNINSERT DESTINATION DISK,TYPE RETURNE}`  `8 rL1`-* 1P* 1 y0Y`hhL!NAME OF FILE TO MOVE?- 0 0|DL% <.F},^ 1 70 0 .@L# .BJ 1  DEHIB V L1 ,} 1 70,L.  G}JB|,#P#DE 1 HI BDEHHII 1 B 1 ,^ 1 70,0La- B V,#PH},^ 1 70 0L#L!-* 1P* 1 y0Yj383}mm ݭI}}`8}``|* ? ɛ,`|:-)| / 1L!`DESTINATION CANT BE DOJ}S.SYS0 0H{ 24Δ 28/L!/) 2 Π 2 0 ξK}hAΞB,0 J 1 BDEHI,HÝDE 1HIHIDELSAVE-GIVE L}FILE,START,END(,INIT,RUN)O S0 1`BDEPHI V` S0H 1 L!M}0 0 1L~0`PLEASE TYPE 1 LETTER,0`hhL! 70 1L0L<1 ,;ɛ7,"ɛ:ݦ1ݥN}A"D|ݤD|ȩ:|ȩ|ɛ,,(/+.ީ1 1,ɛ`轤{NAMEO} TOO LONG B VL!` L1I H1EΝDL1|mDiE` V0`8d/8 i:222 1 LP}!ERROR- 138ɛ+,' 20*.. өr2 1``2TOO MANY DIGITSINVALID HEXAQ}DECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8uR} ECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8u8gGET1FPN_ATOF POPAX_FTOA$RTN1FPN B ` B  B ` B T}آ0 -- ɀ)ȩ`B ` B  B ` B B phGXE-Bank Programmer's ManualHhp 4Copyright 1992 by Duane Tribe July 19, 19925 V} OVERVIEW This package provides CC65 programs access to the 64K of extended memory in an Atari 130XE W} or compatibly-expanded Atari computer as an alternate memory space. Although the access may be slow, the routines X} enable C programs to perform many new and larger tasks. The routines are grouped into several object files; see t Y}he User's Manual for descriptions of each routine. XE MEMORY LAYOUT The XE memory is organi Z}zed as 4 banks of 16K bytes each. To access one of the banks, main memory from 0x4000 to 0x7FFF is replaced by the [} XE memory bank. This memory range is the "access window". The routines are limited to just 64K because CC65 cann \}ot directly manipulate values larger than 16 bits. The bits in the address are interpreted as: ]} BBAA AAAA AAAA AAAA where BB - Bank number (0..3) AA AAAA AAAA AAAA - Address in ^} bank (0..16383) This is converted to a bank selection byte: 1110 BB11 and an address in _} main memory: 01AA AAAA AAAA AAAA DYNAMIC MEMORY Memory blocks are allocated from `} a linked list of free blocks. The word _freelis points to the first free block. The list then progresses linearl a}y up through the XE memory space. Blocks are allocated by finding the first free block that is as large as or b} larger than the requested block. If the block that is chosen is at least 4 bytes larger than the request, the excess b c}ytes are split off as a new free block. 1 Each block, eith d}er allocated or free, is composed as: +-- Address of block | v SS NN... e} where SS - Size of the block (2 to 65534) NN - Address of next free block (if in the free li f}st) NN... - Data bytes (if the block is in use) Every block has a "size" word (SS) just before the block' g}s address. If the block is in the free list, the first two data bytes (NN) are used as a pointer to the next free h}block. A NULL pointer indicates the end of the free block list. Thus, there is a 2-byte overhead per block, i}with a minimum of 4 bytes total used per block. The size of the block is only limited by how much contiguous unuse j}d memory is available. The block release routine, xfree(), automatically merges adjacent free blocks. But as k} blocks are allocated and only some released, the XE memory space may become fragmented. The user can reduce fragmentat l}ion by allocating long-term use memory blocks first. 6502 SUBROUTINES This is a set of mach m}ine language subroutines used by the C routines to access the XE memory. The calling routine must swap in the n} appropriate XE bank into the access window as needed and return main memory to that window before exiting. These o}subroutines must not be called by routines under the access window. The routines access XE memory bytes throu p}gh two sets of zero-page pointers and bank numbers: -xbank1- and -xaddr1-, or -xbank2- and -xaddr2-. q} The bytes -xbank1- and -xbank2- are the bank number along with other bits for the PIA port. The 2-byte point r}ers -xaddr1- and -xaddr2- are the corresponding addresses within the access window. These symbols are s} not resolved by the linking process: xbase = $96 xaddr1 = $98 xbank1 = $9A xaddr2 t} = $9B xbank2 = $9D Each of the routines returns with the 6502 A and X registers u} 2 scrambled. The value in the Y register remains intact. GxpointH ld v}y #[addr flag] jsr xpoint Convert 16-bit XE memory address in -xbase- to a bank number and access w}window address. If Y (the 6502 Y register) is 0, the data are stored at -xbank1- and -xaddr1-; if Y is 3, then x}-xbank2- and -xaddr2- are used instead. Does not actually bring the bank into view; see Access Window y} Control below. GxincrH ldy #[addr flag] jsr xincr If Y is 0, increments -xa z}ddr1-,-xaddr1-+1 to point to next byte in the XE-bank access window. If the address is beyond the access window, {} the address is wrapped back to the start of the window and -xbank1- is incremented. If Y is 3, then -xbank2 |}- and -xaddr2- are used instead. If the address crosses a 16K boundary, the new bank will be placed in t }}he access window, 4even if main memory was in the access window5. GxdecrH ldy #[addr flag] js ~}r xdecr If Y is 0, decrements -xaddr1-,-xaddr1-+1 to point to next byte in the XE-bank access window }. If the address is beyond the access window, the address is wrapped back to the end of the window and -xbank1- is } decremented. If Y is 3, then -xbank2- and -xaddr2- are used instead. If the address crosses a 16K bo }undary, the new bank will be placed in the access window, 4even if main memory was in the access window5.  }GAccess Window ControlH To swap the bank in -xbank1- into the access window, use lda xbank1 } sta $D301 To swap the bank in -xbank2- into the access window, use lda xbank2 } sta $D301 3 To return main memory to the access window, use } lda #$F3 sta $D301 GExampleH To reference the byte at 0x1234 in XE memory: } lda #$34 sta xbase lda #$12 sta xbase+1 ldy #0 jsr xp }oint lda xbank1 sta $D301 lda (xaddr1),y Do not reference subsequent byt }es by incrementing Y unless you can be sure that the target address will not fall outside the access window. Inste }ad, use -xincr-: jsr xincr lda (xaddr1),y -xincr- will handle the necessary bank } swapping when crossing the bank boundaries at 0x0000, 0x4000, 0x8000, and 0xC000. In this example it was not } necessary to call -xpoint-. The -xbank1- and -xaddr1- values could have been computed by hand and stored d }irectly: lda #$E3 ; bank 0 sta xbank1 lda #$52 ; $12 into window sta }xaddr1+1 lda #$34 ; low byte sta xaddr1 Remember to return main memory to the access wind }ow before attempting to access main memory that may reside under the window. } 4 Z XE-Bank Programmer's Manual Copyright 1992 by Duane Tribe July 19, 1992 OVERVIEW } This package provides CC65 programs access to the 64K of extended memory in an Atari 130XE or compatibly-expand}ed Atari computer as an alternate memory space. Although the access may be slow, the routines enable C programs to} perform many new and larger tasks. The routines are grouped into several object files; see the User's Manual} for descriptions of each routine. XE MEMORY LAYOUT The XE memory is organized as 4 banks of 16K }bytes each. To access one of the banks, main memory from 0x4000 to 0x7FFF is replaced by the XE memory bank. This} memory range is the "access window". The routines are limited to just 64K because CC65 cannot directly manip}ulate values larger than 16 bits. The bits in the address are interpreted as: BBAA AAAA AAAA AAAA } where BB - Bank number (0..3) AA AAAA AAAA AAAA - Address in bank (0..16383) } This is converted to a bank selection byte: 1110 BB11 and an address in main memory: } 01AA AAAA AAAA AAAA DYNAMIC MEMORY Memory blocks are allocated from a linked list of free }blocks. The word _freelis points to the first free block. The list then progresses linearly up through the XE mem}ory space. Blocks are allocated by finding the first free block that is as large as or larger than the reques}ted block. If the block that is chosen is at least 4 bytes larger than the request, the excess bytes are split off} as a new free block. 1 Each block, either allocated or free, i}s composed as: +-- Address of block | v SS NN... where } SS - Size of the block (2 to 65534) NN - Address of next free block (if in the free list) NN... - Da}ta bytes (if the block is in use) Every block has a "size" word (SS) just before the block's address. If the} block is in the free list, the first two data bytes (NN) are used as a pointer to the next free block. A NULL pointer }indicates the end of the free block list. Thus, there is a 2-byte overhead per block, with a minimum of 4 byt}es total used per block. The size of the block is only limited by how much contiguous unused memory is available.} The block release routine, xfree(), automatically merges adjacent free blocks. But as blocks are allocated a}nd only some released, the XE memory space may become fragmented. The user can reduce fragmentation by allocating }long-term use memory blocks first. 6502 SUBROUTINES This is a set of machine language subroutines} used by the C routines to access the XE memory. The calling routine must swap in the appropriate XE bank int}o the access window as needed and return main memory to that window before exiting. These subroutines must not be }called by routines under the access window. The routines access XE memory bytes through two sets of zero-page} pointers and bank numbers: xbank1 and xaddr1, or xbank2 and xaddr2. The bytes xbank1 and xbank2 are the bank numb}er along with other bits for the PIA port. The 2-byte pointers xaddr1 and xaddr2 are the corresponding addresses w}ithin the access window. These symbols are not resolved by the linking process: xbase = $96 } xaddr1 = $98 xbank1 = $9A xaddr2 = $9B xbank2 = $9D Each of the routines returns wit}h the 6502 A and X registers 2 scrambled. The value in the Y registe}r remains intact. xpoint ldy #[addr flag] jsr xpoint Convert 16-bit XE memory address} in xbase to a bank number and access window address. If Y (the 6502 Y register) is 0, the data are stored at xban}k1 and xaddr1; if Y is 3, then xbank2 and xaddr2 are used instead. Does not actually bring the bank into view}; see Access Window Control below. xincr ldy #[addr flag] jsr xincr If Y is 0, i}ncrements xaddr1,xaddr1+1 to point to next byte in the XE-bank access window. If the address is beyond the access windo}w, the address is wrapped back to the start of the window and xbank1 is incremented. If Y is 3, then xbank2 and xa}ddr2 are used instead. If the address crosses a 16K boundary, the new bank will be placed in the access windo}w, even if main memory was in the access window. xdecr ldy #[addr flag] jsr xdecr If }Y is 0, decrements xaddr1,xaddr1+1 to point to next byte in the XE-bank access window. If the address is beyond the acc}ess window, the address is wrapped back to the end of the window and xbank1 is decremented. If Y is 3, then xbank2} and xaddr2 are used instead. If the address crosses a 16K boundary, the new bank will be placed in the acces}s window, even if main memory was in the access window. Access Window Control To swap the bank in xbank}1 into the access window, use lda xbank1 sta $D301 To swap the bank in xbank2 into the a}ccess window, use lda xbank2 sta $D301 3 } To return main memory to the access window, use lda #$F3 sta $D301 Example } To reference the byte at 0x1234 in XE memory: lda #$34 sta xbase lda #$12 sta } xbase+1 ldy #0 jsr xpoint lda xbank1 sta $D301 lda (xadd}r1),y Do not reference subsequent bytes by incrementing Y unless you can be sure that the target address will} not fall outside the access window. Instead, use xincr: jsr xincr lda (xaddr1),y }xincr will handle the necessary bank swapping when crossing the bank boundaries at 0x0000, 0x4000, 0x8000, and 0xC000. } In this example it was not necessary to call xpoint. The xbank1 and xaddr1 values could have been computed by} hand and stored directly: lda #$E3 ; bank 0 sta xbank1 lda #$52 ; $12 into win}dow sta xaddr1+1 lda #$34 ; low byte sta xaddr1 Remember to return main memory }to the access window before attempting to access main memory that may reside under the window. } 4 lXE-BANK 1.0 for CC65February 1993By Duane Tribe,120 112th St.Orofino, ID 83544OVERVIEWXE-Bank a collection of rout}ines forCC65 in object-file form that that giveC programs access to the 64K ofextended memory in an XE-compatibleAtari co}mputer. This is version 1.0,released February 1993.The routines were developed on an Atari800XL expanded via the ICD Ram}boXLexpansion running SpartaDOS X 4.20.All files in the XE-BANK package arecopyright 1993 by Duane Tribe. Thepackage ca}n be freely distributed, butthe files listed in the manifest belowmust be included in their originalform. No fee may be c}harged for thispackage other than a nominal mediacharge. There is no warranty of anykind for this software.MANIFESTF}P.OBJ 191 7-22-92 10:42p Defines the float-ASCII conversion routines ftoa() and atof() for use by the progra}m TEST1.C. Look for FP65, a complete set of FP routines for CC65!PROGMAN.ESC 7340 2-04-93 9:34pPROGMAN.TXT 71}08 2-04-93 9:35p The XE-Bank Programmer's Manual. Describes how the XE-Bank routines work and how to write your own }6502 subroutines to access the XE memory. Formatted for a 80x66 page. The .ESC version includes Epson ESC/P codes, t}he .TXT version does not.README 2626 2-24-93 3:27p This file.TEST1.C 4844 9-27-92 12:51aTEST1.LNK } 130 9-28-92 6:14p Test program 1 (access routines) source code and link file.TEST2.C 1499 9-26-92 9:26}pTEST2.LNK 130 9-28-92 6:15p Test program 2 (dynamic allocation) source code and link file.TESTMAN.TXT 406}1 2-24-93 3:04p Description and compilation instructions for the two test programs, formmated for a 80x66 page.USE}RMAN.ESC 10694 2-04-93 9:41pUSERMAN.TXT 10201 2-04-93 9:41p The XE-Bank User's Manual. Describes how to use the} routines to access the XE memory from CC65. Formatted for a 80x66 page. The .ESC version includes Epson ESC/P codes,} the .TXT version does not.XACCESS.OBJ 425 7-23-92 8:02pXCORE.OBJ 269 7-23-92 6:49pXDYNAMIC.OBJ 1797 7-}23-92 6:30pXFILE.OBJ 732 7-24-92 5:01pXSTRING.OBJ 339 9-26-92 8:37pXTRANS.OBJ 280 7-19-92 1:11p T}he object files containing the XE-Bank routines. See the user's manual for details.XEND.OBJ 24 6-29-92 10:30p} Defines the symbol XE_END for use by the test programs only.ACKNOWLEDGEMENTSICD, RamboXL and SpartaDOS X aretrade}marks of ICD, Inc.Atari, 130XE and 800XL are trademarksof Atari Corp.Epson and ESC/P are trademarks of SeikoEpson Corp.}arks of ICD, Inc.Atari, 130XE and 800XL are trademarksof Atari Corp.Epson and ESC/P are trademarks of SeikoEpson Corp./* * XE Bank Memory Access Test */#include "D:stdio.h"#define BUFSIZ 256extern int errno;XE_END();xebank();char b}uffer[BUFSIZ];char f1[6], f2[6];char asc1[20], asc2[20];char rwmesg[] = "%u bytes %s %s (%d) %s %d\n";int retcode;}transfer (name)char *name;{ FILE *file; int i, b, xptr; char *a; if (name) { printf("\nmain2x...\n"); f}ile = fopen(name, "r"); if (file == 0) { printf("file %s?\n", name); return; } xptr = 0; do} { i=fread(buffer, 1, BUFSIZ, file); printf("Read %u bytes", i); main2x(buffer, 0, xptr, i); pri}ntf(".\n"); xptr += i; } while (i==BUFSIZ); printf("%u bytes total\n", xptr); fclose(file); } print}f("\nx2main...\n"); xptr = 0; for (;;) { x2main(buffer, 0, xptr, BUFSIZ); for (i=0; i "); fgets(line, 40, stdin); lp = line; arg0 = getarg(); arg1 = getarg(); arg2 = getarg(}); arg3 = getarg(); switch (toupper(*arg0)) { case 'Q': /* quit */ quit = 1; break; case '}T': /* transfer [file] */ if (*arg1 == '\0') transfer(NULL); else transfer(arg1); break;} case 'I': /* int addr [value] */ xptr = atoi(arg1); printf("int at %u is ", xptr); if (*arg2 == '\0'}) { old = xint(xptr, 0); printf("%d\n", old); } else { new = atoi(arg2); } old = xint(xptr, 0, new); printf("%d, was %d\n", new, old); } break; case 'C': /* cha}r addr [value] */ xptr = atoi(arg1); printf("char at %u is ", xptr); if (*arg2 == '\0') { o}ld = xchar(xptr, 0); printf("'%c'(%d)\n", old, old); } else { new = atoi(arg2); old} = xchar(xptr, 0, new); printf( "'%c'(%d), was '%c'(%d)\n", new, new, old, old); } br}eak; case 'F': /* float addr [value] */ xptr = atoi(arg1); printf("float at %u is ", xptr); if (*arg}2 == '\0') { retcode = xfloat(f1, xptr, 0); ftoa(f1, asc1); printf("%s\n", asc1); } } else { atof(f2, arg2); retcode=xfloat(f1, xptr,0, f2); ftoa(f1, asc1); printf("%s, w}as %s\n", arg2, asc1); } break; case '2': /* 2ndfloat addr value */ xptr = atoi(arg1); } printf("float at %u is ", xptr); atof(f2, arg2); retcode = xfloat(0, xptr, 0, f2); printf("now %s\n", }arg2); break; case 'R': /* read addr len file */ xptr = atoi(arg1); length = atoi(arg2); file} = fopen(arg3, "r"); if (file == NULL) { printf("%s?", arg3); break; } printf(rwmesg}, length, "from", arg3, file, "to", xptr); new=xread(xptr, 0, length, file); printf("%u bytes read\n", }new); printf("errno = %d\n", errno); fclose(file); break; case 'W': /* write addr len file */ } xptr = atoi(arg1); length = atoi(arg2); file = fopen(arg3, "w"); if (file == NULL) { printf}("%s?", arg3); break; } printf(rwmesg, length, "to", arg3, file, "from", xptr); new=xwrit}e(xptr,0, length, file); printf("%u bytes written\n", new); printf("errno = %d\n", errno); fclose(file);} break; case 'Z': /* zero addr length */ xptr = atoi(arg1); length = atoi(arg2); xmemset(xptr,} 0, 0, length); break; case 'L': /* length addr */ xptr = atoi(arg1); length = xstrlen(xptr, 0); } printf("length XE[%d] = %d\n", xptr, length); break; case 'E': /* equal addr string */ xptr = }atoi(arg1); length = xstrcmp(xptr, 0, arg2); printf("XE[%d] - '%s' = %d\n", xptr, arg2, length); } break; case 'A': printf("START: %04X\n", xebank); printf(" END: %04X\n", XE_END); break; case }'?': default: printf( "[QTICF2RWDAZLE] arg...\n"); break; } }}E_END); break; case ^D:RUNTIME.OBJD:XCORE.OBJD:XACCESS.OBJD:XTRANS.OBJD:XFILE.OBJD:XDYNAMIC.OBJD:XSTRING.OBJD:XEND.OBJFP.OBJTEST1.OBJD:C}.OLBTIME.OBJD:XCORE.OBJD:XACCESS.OBJD:XTRANS.OBJD:XFILE.OBJD:XDYNAMIC.OBJD:XSTRING.OBJD:XEND.OBJFP.OBJTEST1.OBJD:C/* * XE Bank Memory Access Test */#include "D:stdio.h"extern char *_freelist;XE_END();traverse(){ char *block; ! } for ( block = _freelist; block != 0; block = xint(block, 0)) { printf("Block %04X, %u bytes\n", bloc! }k, xint(block, -2)); }}char line[40];main (argc, argv)int argc;char *argv[];{ int quit; char *addr, *len; if! } (!xebank()) { printf("no XE memory available\n"); exit(); } xinit(65534); quit = 0; while (!quit) { ! } printf("\nTEST> "); fgets(line, 40, stdin); switch (toupper(*line)) { case 'Q': /* quit */ quit = ! }1; break; case 'A': /* allocate */ len = atoib(line+2, 10); addr = xalloc(len); printf("Allocat!}ed %u at %04x\n", len, addr); break; case 'F': /* free */ addr = atoib(line+2, 10); xfree(addr!}); printf("Freed at %04x\n", addr); break; case 'T': /* traverse */ traverse(); break; case!} 'I': /* initialize */ len = atoib(line+2, 10); xinit(len); break; case 'E': printf("%04X\n", XE!}_END); break; case '?': printf("%s%s%s%s%s%s%s", "A len - allocate\n", "F addr - free\n", !} "T - traverse\n", "Q - quit\n", "I - initialize\n", "E - end address\n", !} "X - existence\n"); break; default: printf("%s?\n", line); } }} - end address\n", dD:RUNTIME.OBJD:XCORE.OBJD:XACCESS.OBJD:XTRANS.OBJD:XFILE.OBJD:XDYNAMIC.OBJD:XSTRING.OBJD:XEND.OBJFP.OBJTEST2.OBJD:C%}.OLBTIME.OBJD:XCORE.OBJD:XACCESS.OBJD:XTRANS.OBJD:XFILE.OBJD:XDYNAMIC.OBJD:XSTRING.OBJD:XEND.OBJFP.OBJTEST2.OBJD:C$ TEST PROGRAMS The two programs TEST1.C and TEST2.C were used to debug the XE Bank routines during th)}eir development. They serve as a good example of how to use the routines. The program files assume that they)} and the CC65 files STDIO.H, C0F1.OLB and RUNTIME.OBJ are all in the current drive and/or directory. In SpartaDOS )}X, I used the commands: X CC65 TEST1.C X RA65 TEST1.M65 X LINK65 -O TEST1.COM @TEST1.LNK )} The files are written using the ASCII curly brace characters instead of the $( $) pairs. Each program)} presents you with the prompt TEST> at which you may enter the listed commands. The first word is )}the command, of which only the first character is significant. The commands are not case sensitive. The remaining)} words are arguments; supply data in these positions. Arguments listed inside [ and ] characters are optional. )} TEST1.C This program tests each of the XE Bank access routines. The arguments must be given in)} signed decimal integer format, except for "fvalue", "file" and "str" arguments. QUIT Quit the program. ) } TRANSFER [file] If "file" is given, use main2x() to read a file into XE memory, st)!}arting at 0x0000. Be sure to specify the complete filespec. Then, x2main() is used to copy the contents of XE)"} memory back to E:, starting from 0x0000 to the first zero byte. INT addr [value])#} Prints the 16-bit integer at "addr". Then, if "value" is given, sets the 16-bit integer at "addr")$} to "value". CHAR addr [value] Prints the character at "addr". Then, if "value" is given, )%} sets the character at "addr" to "value". FLOAT addr [fvalue] Prints the 6-byte flo)&}at at "addr". Then, if "fvalue" is given, sets the 6-byte float at "addr" to "fvalue". )'} 1 2NDFLOAT addr fvalue Sets the 6-byte float at "addr" to "fvalue" w)(}ithout reading the old value. READ addr len file Reads "len" bytes from "file" d))}irectly to "addr". WRITE addr len file Writes "len" bytes from directly from "addr" to "file")*}. ZERO addr len Stores "len" zeros starting at "addr". LENGTH addr )+} Prints the length of the C string starting at "addr". EQUAL addr str Compares the C str),}ing at "addr" to the string "str". Due to the command parsing algorithm, "str" may not contain whi)-}tespace. ADDRESS Prints the starting address and the ending address of the XE-Bank routines i).}n main memory. The routines may not extend into the memory access window. TEST2.C T)/}his program tests the dynamic memory allocation routines. The arguments must be given in unsigned decimal integer forma)0}t. QUIT Quit the program. ALLOCATE len Requests allocation of "len" byt)1}es. Either prints the address of the block or 0x0000 if the request could not be fulfilled. )2}FREE addr Returns memory block starting at "addr" to the free memory list. TRAVE)3}RSE Traverses the free memory list, printing the address of each free block. INI)4}TIALIZE Re-initializes the XE-Memory bank for dynamic access. END Prints the last address)5} of main memory used by the XE-Bank routines. )6} 2 (= phGXE-Bank User's ManualHhp 4Copyright 1992 by Duane Tribe September 28, 19925 -8} OVERVIEW This package provides CC65 programs access to the 64K of extended memory in an Atari 130XE -9}or compatibly-expanded Atari computer as a single alternate memory space. Although the access may be slow, the rou-:}tines enable C programs to per form many new and larger tasks. The package consists of several .OBJ files that mu-;}st be linked immediately after RUNTIME.OBJ: XCORE.OBJ Contains a routine to check for the availability of-<} XE memory, and utility subroutines that are used by all the other routines. This obje-=}ct file must be used; the rest may be used as needed. XDYNAMIC.OBJ Contains routines that allocate b->}locks of memory for use, or release previously allocated blocks for re-use. The memory-?} blocks can be allocated and released in any order. XACCESS.OBJ Contains routines that reference an-@}d optionally assign the primitive C data types integer, character, and float. XS-A}TRING.OBJ Contains routines that find the length of a string in XE memory, compare a string in main memory-B} to one in XE memory, and set a value to a range of XE memory. XTRANS.OBJ Contains routines that t-C}ransfer blocks of bytes to and from XE memory. XFILE.OBJ Contains routines that read directly fro-D}m a file to XE memory, or write directly from XE memory to a file. The dynamic memory routines -E}will never use 0x0000 as a valid address for any memory block, so the standard C use of NULL pointers still applies-F}. If only a fixed amount of XE memory is needed, the user can skip the dynamic memory routines and treat the XE memory -G}as a giant array of 65536 bytes. The pointer to the list of free blocks is available from C, see the Programmer's -H}Manual for details. There is no restriction on where the user's C program and data reside in main memory. Da-I}ta in XE memory can straddle 16K boundaries without problems. This package claims all 64K of XE memory for us-J}e by C programs. Users with only 64K of XE memory (such as unmodified 130XE computers) must give up their internal-K} RAM disks and cannot use SpartaDOS X "USE BANKED" configurations. Extra memory beyond the 64K XE memory (such as -L}with a RamboXL upgraded computer) is unaffected and is free for use by other programs such as RAM disks or SpartaDOS X.-M} 1 The routines do not disable interrupts when accessing the XE -N}memory. If there is display list data in the memory from 0x4000 to 0x7FFF, the display will flicker when XE memory-O} is accessed. If the OS calls an interrupt routine located in memory from 0x4000 to 0x7FFF, the computer will lock-P} up. These problems can be prevented by being sure that any display lists or interrupt routines are located below 0x400-Q}0 (such as page 6) or above 0x7FFF. PARAMETERS Regular C pointers are used as pointers into-R} the XE memory space. Binary operations between pointers in XE memory are valid, but binary operations between a p-S}ointer in XE memory and one in main memory are meaningless. All the regular C pointer operations are valid, except -T} -*- -->- and -[]- since CC65 will assume that the pointer is in main memory. Many routines use t-U}wo parameters, -p- and -offset-, to access one location in XE memory. This is done to mimic the C operators --V}->-, as in -p->offset-, or -[]-, as in -p[offset]-. However, -offset- is always a 4byte5 offse-W}t away from -p-. When simulating a C struct, -offset- is calculated by adding up the bytes used by th-X}e preceding fields. For example, given the binary tree node structure struct node { -Y}struct node *left; struct node *right; char word[10] }; to allocate a new node, use-Z} a = xalloc(14); The field -right- is at offset 2. To access value of -right-, use -[} b = xint(a, 2); When no offset is needed, use zero for the -offset- parameter. Be sure to s-\}upply an appropriate number of parameters for each routine. They do not check for an illegal number of parameters. Thi-]}s may be a hard bug to spot because some routines accept two different parameter counts; see XACCESS.OBJ below. -^} 2 XCORE.OBJ GxebankH int xebank(-_}) Returns TRUE (1) if running on an Atari 130XE or a compatibly-expanded Atari computer, otherwise returns FA-`}LSE (0). Use to prevent system lock-up on unexpanded computers. XDYNAMIC.OBJ GxinitH -a} xinit() Initialize the XE memory space for allocation. At first, the memory is one 65534 byte free b-b}lock. May be used to deallocate all the memory at once. GxallocH char *xalloc(size) int si-c}ze - Number of bytes to allocate Returns pointer to first free block of memory capable of holding -size- -d}bytes. The memory is not initialized. If there is not a contiguous block of -size- bytes free in XE memory, return-e}s NULL. GxfreeH xfree(p) char *p - pointer to memory block Frees up memory block at -f}-p- in XE memory for later use by xalloc(). The value of -p- 4must5 have been returned from a previous call to-g} xalloc. XACCESS.OBJ GxintH int xint(p, offset) char *p - pointer to m-q}B%DOS SYSB*)DUP SYSBSFP OBJB;UPROGMAN ESCB9PROGMAN TXTBREADME B'TEST1 C BTEST1 LNKB TEST2 C BTEST2 LNKB!TESTMAN TXTBV7USERMAN ESCBRUSERMAN TXTBXACCESS OBJBXCORE OBJBXDYNAMICOBJBXEBANK TXTB XEND OBJB XFILE OBJBXSTRING OBJBXTRANS OBJemory block int offset - byte offset into block Returns integer at -p-+-offset- in XE memory. -r} 3 int xint(p, offset, value) char *p - pointer to memory bl-s}ock int offset - byte offset into block int value - replacement value Sets integer at -p-+-offset-t}- in XE memory to -value- and returns the previous integer at that location. The return value may be ignored. -u} GxcharH int xchar(p, offset) char *p - pointer to memory block int offset - byte offset int-v}o block Returns character at -p-+-offset- in XE memory. int xchar(p, offset, value) char *-w}p - pointer to memory block int offset - byte offset into block int value - replacement value Sets c-x}haracter at -p-+-offset- in XE memory to -value- and returns the previous character at that location. The r-y}eturn value may be ignored. GxfloatH char *xfloat(f, p, offset) char *f - pointer to flo-z}at buffer char *p - pointer to memory block int offset - byte offset into block Copies 6 bytes (a ROM-{} float) from -p-+-offset- in XE memory to -f- in main memory. Returns -f-. char *xfloat(f, p-|}, offset, value) char *f - pointer to float buffer char *p - pointer to memory block int offset - byt-}}e offset into block char *value - replacement value If -f- is not NULL, copies 6 bytes (a ROM float) from-~} -p-+-offset- in XE memory to -f- in main memory. Copies 6 bytes from -value- in main memory to --}p-+-offset- in XE memory. Returns -f-. 4 -} XSTRING.OBJ GxmemsetH xmemset(p, offset, byte, length) char *p - pointer to memory block-} int offset - byte offset into block int byte - byte to write to XE bank int length - number of bytes to swap-} Sets -length- bytes of XE memory starting at -p-+-offset- to -byte-. GxstrlenH -} xstrlen(p, offset) char *p - pointer to memory block int offset - byte offset into block Return-}s the length of the C string beginning at -p-+-offset- in XE memory. If no zero byte is found in XE memory, this-} routine locks up. GxstrcmpH int xstrcmp(p, offset, string) char *p - pointer to memory blo-}ck int offset - byte offset into block char *string - string in main memory Compares -string- in m-}ain memory to a C string in XE memory at -p-+-offset-. Returns comparison code as with strcmp. -}XTRANS.OBJ Gx2mainH x2main(addr, p, offset, length) char *addr - main memory buffer char *-}p - pointer to memory block int offset - byte offset into block int length - byte transfer length Cop-}ies -length- bytes from -p-+-offset- in XE memory to -addr- in main memory. Gmain2xH -} main2x(addr, p, offset, length) char *addr - main memory buffer char *p - pointer to memory block int -}offset - byte offset into block int length - byte transfer length 5-} Copies -length- bytes from -addr- in main memory to -p-+-offset- in XE memory. -} XFILE.OBJ GxreadH int xread(p, offset, length, stream) char *p - pointer to memory block-} int offset - byte offset into block int length - number of bytes to read FILE *stream - source of bytes -} Reads -length- bytes from -stream- directly to -p-+-offset- in XE memory. Returns number of b-}ytes actually read in. GxwriteH int xwrite(p, offset, length, stream) char *p - pointer to -}memory block int offset - byte offset into block int length - number of bytes to write FILE *stream - dest-}ination of bytes Writes -length- bytes directly from -p-+-offset- in XE memory to -stream-. -}Returns number of bytes actually wrote out. -} 6 ,E XE-Bank User's Manual Copyright 1992, by Duane Tribe September 28, 1992 OVERVIEW 1} This package provides CC65 programs access to the 64K of extended memory in an Atari 130XE or compatibly-expand1}ed Atari computer as a single alternate memory space. Although the access may be slow, the routines enable C progr1}ams to perform many new and larger tasks. The package consists of several .OBJ files that must be linked imme1}diately after RUNTIME.OBJ: XCORE.OBJ Contains a routine to check for the availability of XE 1} memory, and utility subroutines that are used by all the other routines. This object file must be used; 1}the rest may be used as needed. XDYNAMIC.OBJ Contains routines that allocate blocks of memory for 1} use, or release previously allocated blocks for re-use. The memory blocks can be allocat1}ed and released in any order. XACCESS.OBJ Contains routines that reference and optionally assign 1} the primitive C data types integer, character, and float. XSTRING.OBJ Contains rou1}tines that find the length of a string in XE memory, compare a string in main memory to one in XE 1} memory, and set a value to a range of XE memory. XTRANS.OBJ Contains routines that transfer blocks of byte1}s to and from XE memory. XFILE.OBJ Contains routines that read directly from a file to XE 1} memory, or write directly from XE memory to a file. The dynamic memory routines will never use 0x0000 1}as a valid address for any memory block, so the standard C use of NULL pointers still applies. If only a fixed amo1}unt of XE memory is needed, the user can skip the dynamic memory routines and treat the XE memory as a giant array 1}of 65536 bytes. The pointer to the list of free blocks is available from C, see the Programmer's Manual for details. 1} There is no restriction on where the user's C program and data reside in main memory. Data in XE memory can st1}raddle 16K boundaries without problems. This package claims all 64K of XE memory for use by C programs. User1}s with only 64K of XE memory (such as unmodified 130XE computers) must give up their internal RAM disks and cannot 1}use SpartaDOS X "USE BANKED" configurations. Extra memory beyond the 64K XE memory (such as with a RamboXL upgrade1}d computer) is unaffected and is free for use by other programs such as RAM disks or SpartaDOS X. 1} 1 The routines do not disable interrupts when accessing the XE memory. If there1} is display list data in the memory from 0x4000 to 0x7FFF, the display will flicker when XE memory is accessed. If the 1}OS calls an interrupt routine located in memory from 0x4000 to 0x7FFF, the computer will lock up. These problems c1}an be prevented by being sure that any display lists or interrupt routines are located below 0x4000 (such as page 61}) or above 0x7FFF. PARAMETERS Regular C pointers are used as pointers into the XE memory space. 1} Binary operations between pointers in XE memory are valid, but binary operations between a pointer in XE memory and1} one in main memory are meaningless. All the regular C pointer operations are valid, except * -> and [] since CC651} will assume that the pointer is in main memory. Many routines use two parameters, p and offset, to access one loc1}ation in XE memory. This is done to mimic the C operators ->, as in p->offset, or [], as in p[offset]. However, o1}ffset is always a byte offset away from p. When simulating a C struct, offset is calculated by adding up the1} bytes used by the preceding fields. For example, given the binary tree node structure struct node 1} { struct node *left; struct node *right; char word[10] }; to all1}ocate a new node, use a = xalloc(14); The field right is at offset 2. To access value of right, us1}e b = xint(a, 2); When no offset is needed, use zero for the offset parameter. Be sure t1}o supply an appropriate number of parameters for each routine. They do not check for an illegal number of parameters. 1}This may be a hard bug to spot because some routines accept two different parameter counts; see XACCESS.OBJ below.1} 2 XCORE.OBJ xebank int xebank()1} Returns TRUE (1) if running on an Atari 130XE or a compatibly-expanded Atari computer, otherwise returns FAL1}SE (0). Use to prevent system lock-up on unexpanded computers. XDYNAMIC.OBJ xinit 1} xinit() Initialize the XE memory space for allocation. At first, the memory is one 65534 byte free block. 1} May be used to deallocate all the memory at once. xalloc char *xalloc(size) int size - Numbe1}r of bytes to allocate Returns pointer to first free block of memory capable of holding size bytes. The memo1}ry is not initialized. If there is not a contiguous block of size bytes free in XE memory, returns NULL. xfr1}ee xfree(p) char *p - pointer to memory block Frees up memory block at p in XE memory for later us1}e by xalloc(). The value of p must have been returned from a previous call to xalloc. XACCESS.OBJ1} xint int xint(p, offset) char *p - pointer to memory block int offset - byte offset into 1}block Returns integer at p+offset in XE memory. 3 1} int xint(p, offset, value) char *p - pointer to memory block int offset - byte offset into block int value1} - replacement value Sets integer at p+offset in XE memory to value and returns the previous integer at that1} location. The return value may be ignored. xchar int xchar(p, offset) char *p - pointer to me1}mory block int offset - byte offset into block Returns character at p+offset in XE memory. int xch1}ar(p, offset, value) char *p - pointer to memory block int offset - byte offset into block int value - rep1}lacement value Sets character at p+offset in XE memory to value and returns the previous character at that lo1}cation. The return value may be ignored. xfloat char *xfloat(f, p, offset) char *f - poin1}ter to float buffer char *p - pointer to memory block int offset - byte offset into block Copies 6 by1}tes (a ROM float) from p+offset in XE memory to f in main memory. Returns f. char *xfloat(f, p, offset, valu1}e) char *f - pointer to float buffer char *p - pointer to memory block int offset - byte offset into 1}block char *value - replacement value If f is not NULL, copies 6 bytes (a ROM float) from p+offset in XE 1} memory to f in main memory. Copies 6 bytes from value in main memory to p+offset in XE memory. Returns f. 1} 4 XSTRING.OBJ xmemset xmemset(p, offset1}, byte, length) char *p - pointer to memory block int offset - byte offset into block int byte - byte to 1}write to XE bank int length - number of bytes to swap Sets length bytes of XE memory starting at p+offset to 1}byte. xstrlen xstrlen(p, offset) char *p - pointer to memory block int offset - byte offse1}t into block Returns the length of the C string beginning at p+offset in XE memory. If no zero byte is found 1}in XE memory, this routine locks up. xstrcmp int xstrcmp(p, offset, string) char *p - pointer1} to memory block int offset - byte offset into block char *string - string in main memory Compares str1}ing in main memory to a C string in XE memory at p+offset. Returns comparison code as with strcmp. XTRA1}NS.OBJ x2main x2main(addr, p, offset, length) char *addr - main memory buffer char *p - po1}inter to memory block int offset - byte offset into block int length - byte transfer length Copies lengt1}h bytes from p+offset in XE memory to addr in main memory. main2x main2x(addr, p, offset, length)1} char *addr - main memory buffer char *p - pointer to memory block int offset - byte offset into block 1}int length - byte transfer length 5 Copies length bytes from ad1}dr in main memory to p+offset in XE memory. XFILE.OBJ xread int xread(p, offset, 1}length, stream) char *p - pointer to memory block int offset - byte offset into block int length - nu1}mber of bytes to read FILE *stream - source of bytes Reads length bytes from stream directly to p+offset in X1}E memory. Returns number of bytes actually read in. xwrite int xwrite(p, offset, length, stream)1} char *p - pointer to memory block int offset - byte offset into block int length - number of bytes to1} write FILE *stream - destination of bytes Writes length bytes directly from p+offset in XE memory to stream.1} Returns number of bytes actually wrote out. 1} 6 0LNSGETADDR_XINT_XFLOATPOPAX_XCHARMXPOINTXINCR  C   @5} E ӱ  F  ӥ`  C  @ E ӱ 5} ӥ`  C ݩ @ E C Ӡ F擥 E5} F擥ӭ  ` E C Ӡ F擥 E42CGETADDR\POPAXXPOINTXINCRXDECR9_XEBANKq)?i@)JJJJ 㕚`@9}i) 㕚`֙?8) 㕚֘` A A ee`@ө5ӱ59} `֙?8) 㕚֘` A A ee`@ө5ӱ58Q_XALLOCDPOPAX __FREELISXPOINTXINCR_XINIT_XFREE=}@Ӡȩȩȑ  ` A            =}  ө`8   Cӱ  D 8           =}D  D L s   L  m   m  8   Cӭ  D=}  D  D 8       Cӭ  D  D  D =} i  i L    Cӱ  D       L   =} Cӭ  D ӭ  ` A          ?8  =}  0       Cӱ  D L   [8   C=}ӱ  D  m  m ii8   8   Cӱ =}  D   5 m  m ii8   )68  =} Cӱ  D  D  D )s m   m   i  i ) =} i i e  e 8   Cӭ  D L      =} L    Cӭ  D !   Cӭ  D V =}m  m i i 8   Cӭ  D  D  D ! =}  Cӭ  D `  Cӭ  D  D  D ! </XE-BANK V1.0 February 1993 Duane Tribe 120 112th st. Orofino, ID 83544 This archive contains object files for CC65 that proA}vide functions for accessing the extra 64K of data in 130XE-compatable computers directly from C programs. The files are in B}Atari format (i.e. newline=155). Also, beware of using the program TEST1.C with the FP65 archive. The FP.OBJ file in this aB}rchive is incompatable with FP65, as the arguments of ftoa() are reversed. These files are Copyright 1993 by Duane Tribe. TB}hey may be freely distributed so long as all the files (including this one) remain in their original form. You may use and mB}odify the source code for your own purposes. No fee, other than a nominal media charge, may be required to distribute these fB}iles. There is no waranty of any kind for thgis software. All other rights reserved. MANIFEST FP.OBJ 191 B}22 Jul 92 10:42p PROGMAN.ESC 7340 4 Feb 93 9:34p PROGMAN.TXT 7108 4 Feb 93 9:35p README B} 2626 24 Feb 93 3:27p TEST1.C 4844 27 Sep 92 12:51a TEST1.LNK 130 28 Sep 92 6:14p TEST2.C B} 1475 27 Sep 92 12:49a TEST2.LNK 130 28 Sep 92 6:15p TESTMAN.TXT 4061 24 Feb 93 3:04p USERMB}AN.ESC 10694 4 Feb 93 9:41p USERMAN.TXT 10201 4 Feb 93 9:41p XACCESS.OBJ 425 23 Jul 92 8:02B }p XCORE.OBJ 269 23 Jul 92 6:49p XDYNAMIC.OBJ 1797 23 Jul 92 6:30p XEND.OBJ 24 29 Jun 92B } 10:30p XFILE.OBJ 732 24 Jul 92 5:01p XSTRING.OBJ 339 26 Sep 92 8:37p XTRANS.OBJ 280 19B } Jul 92 1:11p BJ 732 24 Jul 92 5:01p XSTRING.OBJ 339 26 Sep 92 8:37p XTRANS.OBJ 280 19@_XE_END` 732 24 Jul 92 5:01p XSTRING.OBJ 339 26 Sep 92 8:37p XTRANS.OBJ 280 19DEGETADDRPOPAX_XREAD_ERRNOXPOINT_XWRITE A A     @J} D8嘍 噍 8          H IDEB V:ӌCJ}C8       }H  }I  `8        ӭ J} `@i) L ' A A     @ D8嘍 噍 8    J}      H IDE B V:ӌCC8       }H J} }I  `8        ӭ  `@i) L   }H HkTGETADDRPOPAX_XMEMSETXPOINT_XSTRCMPkXINCR_XSTRLEN: A   A @N} C  0   EL ` @ Cӌ   E  L Mӭ  N}` A @ Cӱӥь` EL z80``E  L Mӭ  LYEGETADDRPOPAXXPOINTXINCR_X2MAINF_MAIN2X A   @ A B HR}h C    ` A   @ A B ӱH C h R}   `   ` A   @ A B ӱH C h P