whomper Posted June 22 Share Posted June 22 My assembly project (MAC/65) is growing to massive size, to the point where I need to start at $8500 otherwise I can not debug in DDT while coding. The project consists of a large main file with all app specific code and a utils file that has common macros and functions. If I break the large main file into a few smaller ones, will it make any difference? After all, the assembler loads (#include) all files into memory regardless while assembling. Is there a clever way to overcome the tight memory? Is there a way to use my memory expansion? Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted June 22 Share Posted June 22 (edited) Are you limiting yourself by developing on real h/w only? Cross-developing under an emulators debugger would be more efficient but I appreciate people want to enjoy how it was done originally. Edited June 22 by Wrathchild Quote Link to comment Share on other sites More sharing options...
whomper Posted June 22 Author Share Posted June 22 8 minutes ago, Wrathchild said: Are you limiting yourself by developing on real h/w only? Cross-developing under an emulators debugger would be more efficient but I appreciate people want to enjoy how it was done originally. Yeah, I code on an Atari 800XL, like when I started so long ago. Its so fun to pop in a real floppy and load my code 🙂 For me, I work better under limitations as it forces me to make choices early on. 1 Quote Link to comment Share on other sites More sharing options...
+yetanothertroll Posted June 22 Share Posted June 22 Overlays? Break the code into a main module you keep in main memory at all times plus overlay modules that you read in from disk or copy from the memory expansion as needed. Kind of sort of like a bank switched cart 2 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 22 Share Posted June 22 You mention Macros, you know that each time you use one it's the entire macro code that's inserted, sometimes it's easier to create a subroutine if it's used many times to reduce memory usage 1 Quote Link to comment Share on other sites More sharing options...
Harry Potter Posted June 22 Share Posted June 22 Well, I recommend using my Cubbyhole technique. It states that you can use the portions of memory allocated to the OS that are not being used during the course of your program for your code and data. This can buy a couple k space for your program at the cost of a routine that loads in the stubs. I do this for some cc65 programs, but if your assembler supports overlays, it should be doable there as well. If you don't have one, you need a memory map of both the Atari and your particular DOS to tell you which addresses can be used. Does this help? 1 Quote Link to comment Share on other sites More sharing options...
E474 Posted June 22 Share Posted June 22 Hi, I'm a bit rusty on MAC/65, and am not clear on exactly what you mean by "starting at $8500", but MAC/65 lets you assemble from disk, so you could have 10 small files all included into a MAIN.ASM file, and assemble with something like: ASM #D1:MAIN.ASM,,#D1:MAIN.OBJ See: https://atariwiki.org/wiki/attach/Mac65/MAC65 Assembler.pdf for details. You'd have to edit/save each individual file, which might get a bit tedious, though a Ramdisk might help, given you have a memory expansion. I don't know whether an OS level debugger like Omnimon is an option, I have a SysCheck II, and one of the 4 flashable OS's is QMEG OS, which includes a monitor/debugger, and has been very handy at times. 1 Quote Link to comment Share on other sites More sharing options...
Harry Potter Posted June 22 Share Posted June 22 BTW, if you have a few k free and require a lot of disk space, you might want to try compressing your overlays. Right now, I only know about Exomizer, but I'm working on my own compression techniques and plan to make some of them available for multi-part programs that are too large to fit on one disk image. 1 1 Quote Link to comment Share on other sites More sharing options...
whomper Posted June 24 Author Share Posted June 24 On 6/22/2024 at 8:28 PM, yetanothertroll said: Overlays? Break the code into a main module you keep in main memory at all times plus overlay modules that you read in from disk or copy from the memory expansion as needed. Kind of sort of like a bank switched cart Any code samples on how to switch banks and access what's in the extended banks? Quote Link to comment Share on other sites More sharing options...
Rybags Posted June 24 Share Posted June 24 You can assemble from a source file on disk without need to have it resident in memory. In that case the only low memory used would be by Dos and the work area needed for the assembly process. But yeah, the nostalgia thing might have it's attractions but there can be plenty of pain involved. PC based development can mean a program change and run/test in a few seconds rather than several minutes. 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 24 Share Posted June 24 (edited) 1 hour ago, whomper said: Any code samples on how to switch banks and access what's in the extended banks? Without a cartridge inserted the bank values are $FF Normal memory BANKFLAG1 .BYTE $E3,$E7,$EB,$EF ; Bank values for PORTB I use this code to switch banks in a disk copy program. ; switch to next RAM bank BANK LDX BANKFLAG LDA BANKFLAG1,X STA PORTB CPX #4 BEQ T3 INX STX BANKFLAG LDA #0 RTS T3 LDA #$FF STA PORTB RTS BANKFLAG .BYTE 0 BANKFLAG1 .BYTE $E3,$E7,$EB,$EF ; Bank values for PORTB Memory is accesses through locations $4000 to $7FFF Edited June 24 by TGB1718 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 24 Share Posted June 24 (edited) If you have a U1M you can get the bank values from SDX, I used them in a demo I wrote last year in cc65, I think I used 19 banks for the demo, but here's a list of the PORTB values for each bank // rambank vaues for portb char bank[]= {0xFF,0xE3,0xE7,0xEB,0xEF, 0xE1,0xE5,0xE9,0xED, 0xC3,0xC7,0xCB,0xCF, 0xC1,0xC5,0xC9,0xCD, 0xA3,0xA7,0xAB,0xAF, 0xA1,0xA5,0xA9,0xAD, 0x83,0x87,0x8B,0x8F, 0x81,0x85,0x89,0x8D, 0x63,0x67,0x6B,0x6F, 0x61,0x65,0x69,0x6D, 0x43,0x47,0x4B,0x4F, 0x41,0x45,0x49,0x4D, 0x23,0x27,0x2B,0x2F, 0x21,0x25,0x29,0x2D, 0x03,0x07,0x0B,0x0F,0x01}; You can get this information using MEMINFO on SDX Edited June 24 by TGB1718 Quote Link to comment Share on other sites More sharing options...
Harry Potter Posted June 24 Share Posted June 24 TGB1718: If you want, I have a cc65 memory extension for the Atari 1200XL that gives you an extra 64k memory and allows you to use the RAM that's allocated to the OS but unused during the course of most programs. It is called MemXAtari and available at c65 additions - Manage /memory cfgs at SourceForge.net. I also have AtaDisk65, which provides disk access that's more efficient than the standard cc65 file I/O library, but it's currently limited to opening, reading, writing and closing files but provides the ability to read files into memory easily. It can be found at c65 additions - Manage /ui at SourceForge.net. AtaSimpleIO is also there: it provides a very efficient replacement of functions such as printf() and puts() that interfaces directly with the OS and performs very little extra processing. Try them out and tell me what you think. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 24 Share Posted June 24 With the best will in the world Harry, I've looked at your utilities many times and have yet to find any decent documentation on how to use any of your libraries/code. For example I had a look at MemXAtari_001.txt hoping to see explanations and examples, but all that's there is:- MemXAtari is a library for cc65 that allows easy access to the Atati XL's extra RAM from a cc65 C program. Also provides access to unused sections of Low RAM for your cc65 program. Uses my AtaDisk65 library. Requires an Atari 1200XL. So I had a look in some .C code, it's full of code commented out, sometimes more of that than useable code and dare I say it you've used GOTO in C code 🤬 Oh Dear !!! 14 minutes ago, Harry Potter said: Atari 1200XL that gives you an extra 64k Where is this extra 64K ? 1200XL only has 64K as far as I know 2 1 Quote Link to comment Share on other sites More sharing options...
Harry Potter Posted June 24 Share Posted June 24 I'm sorry about the lack of documentation. At least I tried. I'm pretty sure it was the 1200XL that supported the extra memory, as the library only worked when my emulator was in that mode. Maybe I was thinking about another computer? I have to clean up the code when I get a chance. Quote Link to comment Share on other sites More sharing options...
+yetanothertroll Posted June 24 Share Posted June 24 5 hours ago, whomper said: Any code samples on how to switch banks and access what's in the extended banks? Sorry, not a clue. But between bank switched carts and extended memory, something like IBM PC DOS code overlays could be done https://ftp.zx.net.nz/pub/Patches/ftp.microsoft.com/MISC/KB/en-us/51/416.HTM 4 hours ago, Rybags said: You can assemble from a source file on disk without need to have it resident in memory. In that case the only low memory used would be by Dos and the work area needed for the assembly process. But yeah, the nostalgia thing might have it's attractions but there can be plenty of pain involved. PC based development can mean a program change and run/test in a few seconds rather than several minutes. Well that just leads into the nostalgic coffee breaks, right? 1 Quote Link to comment Share on other sites More sharing options...
Harry Potter Posted June 25 Share Posted June 25 I started a new draft of MemXAtari then checked the header file and found out why there are very few comments there: the function names mimic the functions on which they are based. For example, aux_strlen() will return the length of the string at the given address in aux memory. Some functions also have from, to or in as suffixes. From means aux memory is the source, to aux memory is the destination and in means from aux memory to aux memory. After that, I need to fix all the code. BTW, the reason I use goto in C is I sometimes want to transfer control from one part of a function to another, and a break or continue won't reach. That, and it's there. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 25 Share Posted June 25 2 hours ago, Harry Potter said: That, and it's there. Yes, appreciate that, but I think since I started using C many, many moons ago and maybe millions of lines of code I don't think I ever used a goto I made a small mod to one of your examples that used a goto, just to give you an idea on how easy it is not to use goto. This is from main.c, I left the start label so you can see where I started 👍 Not having a "dig", just trying to be helpful 😇 void main () { printscr ("Loading stubs..."); cio_load (2, "D1:XBUF1.BIN", 0x3FD, 0x303); loadauxmem ("D1:AUX1.BIN"); start: do { clrscr (); printscr ( " Welcome to MadLibAtari by Joseph Rose,\n" " a.k.a. Harry Potter!\n" "---------------------------------------\n" "Please choose the category of a desired\n" "story:\n\n" "a. Science Fiction\n" "b. Fantasy\n" "c. Generic\n\n" "x. Exit" ); cate=getkey(); if (cate=='x') { printscr("Bye! I hope you enjoyed this program.\n" "If you like it, please send me an e-mail" "at rose.joseph12@yahoo.com."); getkey(); return; } cate-='a'; if (cate>=3) illegalcate (); else dispsto2 (); }while(1); } Quote Link to comment Share on other sites More sharing options...
+yetanothertroll Posted June 25 Share Posted June 25 The current orthodoxy in the academic ivory towers is that break, continue, multiple return points, Exit If/Do/For/While, etc., are all just as bad as goto or setjmp/longjmp and will longjmp you right out of the course or even college. In the real world however, goto is almost mandatory to be certain all resources are cleaned up properly before the one and only one return point, especially in the case of other functions returning errors, https://stackoverflow.com/questions/72581672/why-are-goto-break-continue-and-multiple-return-statements-considered-bad-prac 1 Quote Link to comment Share on other sites More sharing options...
Harry Potter Posted June 25 Share Posted June 25 I think I used goto there because I found it to be more efficient. I think that happened on another program also. Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted June 25 Share Posted June 25 In what way? How did the generated assembly differ? Quote Link to comment Share on other sites More sharing options...
+yetanothertroll Posted June 25 Share Posted June 25 3 hours ago, Harry Potter said: I think I used goto there because I found it to be more efficient. I think that happened on another program also. 2 hours ago, Wrathchild said: In what way? How did the generated assembly differ? It's pretty well known that even though structured programming can do everything goto spaghetti code can do, sometimes the structured approach needs more variables or redundant computations to accomplish the same tasks. For example, this (prototype, unoptimized!) FastBasic code has redundant comparisons all over the place, some to skip the Do/Loop, others to figure out exactly why that same Do/Loop exited. A few strategic Gotos would definitely shave off a few CPU cycles! Proc malloc mbufsize If 0 = MFlags(0) Then @MSetup Print "malloc "; mbufsize; " "; ' Convert the requested buffer size to words mbufsize = (((mbufsize + 1) & $FFFE) / 2) & $7FFF Print mbufsize; " "; mbufsize * 2; If MemLo & $8000 Print " regular" ' @free has been used so look for a free block that might be big enough mp = MemLo & $7FFF MemLo = mp ' ...that may or may not still exist Else Print " Express" ' There should be no free blocks to check so jump to extending the heap mp = MemHi EndIf Do ' Are we at the top of the heap already? If mp = MemHi Then Exit msz = MHeap(mp) ' Size of this block in words minus two byte header If msz & $8000 ' This block has been flagged as having been freed MemLo = (MemLo ! $8000) ' Flag that freed blocks exist msz = msz & $7FFF If mbufsize <= msz Then Exit ' It's big enough to satisfy the request ' Otherwise, can it be merged with a following free block? mnp = mp + msz + 1 If mnp = MemHi ' This free block is at the top of the heap with nothing else ' after it, so just pretend it doesn't exist and shrink the heap MemHi = mp ElIf (MHeap(mnp) & $8000) = 0 ' The following block is in use, so skip to the block after it mp = mnp + MHeap(mnp) + 1 Else ' Merge the free blocks, check the size in the next iteration MHeap(mp) = ((msz + (MHeap(mnp) & $7FFF) + 1) ! $8000) EndIf Else ' Block in use, move to the next one mp = mp + msz + 1 EndIf Loop If 0 = mbufsize ' @malloc 0, full of sound and fury, signifying nothing mbufadr = 0 ElIf mp = MemHi ' No free block was big enough, so try to extend the heap MNewHi = mp + mbufsize + 1 If MNewHi <= MemMax MHeap(mp) = mbufsize MemHi = MNewHi mbufadr = &MHeap + (mp * 2) + 2 Else Print "malloc out of heap "; mbufsize; " "; MNewHi; " "; MemMax . Get X mbufadr = 0 EndIf ElIf mbufsize < msz ' The block is bigger than it needs to be, so split it into two MHeap(mp) = mbufsize MHeap(mp + mbufsize + 1) = ((msz - mbufsize - 1) ! $8000) mbufadr = &MHeap + (mp * 2) + 2 ElIf mbufsize = msz ' Goldilocks says the block is already just right MHeap(mp) = msz mbufadr = &MHeap + (mp * 2) + 2 Else ' We should never get here! mbufadr = 0 EndIf EndProc Quote Link to comment Share on other sites More sharing options...
+yetanothertroll Posted June 25 Share Posted June 25 On 6/24/2024 at 5:58 AM, TGB1718 said: ... Where is this extra 64K ? 1200XL only has 64K as far as I know There may have been some bank switched expanded memory scheme. I'd check out the Altirra Hardware Reference Manual sections 2.6 and 2.7 Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted June 25 Share Posted June 25 25 minutes ago, yetanothertroll said: For example Question was asked of Harry as I know he uses CC65. Simple example: static int myVar = 0; void myFunc1(void) { do { myVar++; } while (1); } void myFunc2(void) { myLabel: myVar++; goto myLabel; } void main() { myFunc1(); myFunc2(); } Generates same code: ; ; File generated by cc65 v 2.13.2 ; .fopt compiler,"cc65 v 2.13.2" .setcpu "6502" .smart on .autoimport on .case on .debuginfo off .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2 .macpack longbranch .forceimport __STARTUP__ .export _myFunc1 .export _myFunc2 .export _main .segment "DATA" _myVar: .word $0000 ; --------------------------------------------------------------- ; void __near__ myFunc1 (void) ; --------------------------------------------------------------- .segment "CODE" .proc _myFunc1: near .segment "CODE" L0004: lda _myVar ldx _myVar+1 jsr incax1 sta _myVar stx _myVar+1 jmp L0004 .endproc ; --------------------------------------------------------------- ; void __near__ myFunc2 (void) ; --------------------------------------------------------------- .segment "CODE" .proc _myFunc2: near .segment "CODE" L000A: lda _myVar ldx _myVar+1 jsr incax1 sta _myVar stx _myVar+1 jmp L000A .endproc ; --------------------------------------------------------------- ; void __near__ main (void) ; --------------------------------------------------------------- .segment "CODE" .proc _main: near .segment "CODE" jsr _myFunc1 jmp _myFunc2 .endproc So I was curious to see where goto was more efficient Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 25 Share Posted June 25 8 minutes ago, yetanothertroll said: There may have been some bank switched expanded memory scheme. I'd check out the Altirra Hardware Reference Manual sections 2.6 and 2.7 I understand the bank switching schemes, but Harry implied the 1200XL has an extra 64K which it doesn't. The max RAM available on a 64K machine is 62K if you use the RAM that's "under" the ROM, without having a memory expansion fitted On 6/24/2024 at 1:43 PM, Harry Potter said: I have a cc65 memory extension for the Atari 1200XL that gives you an extra 64k memory and allows you to use the RAM that's allocated to the OS but unused during the course of most programs. 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.