flashjazzcat Posted April 2, 2014 Share Posted April 2, 2014 Previous link I posted doesn't redirect to the desired page, so here's the detection routine from SysInfo, written by KMK: ; Bank select RAM detection ; Stolen from the SysInfo ; ; Must NOT be located within the $4000-$7FFF !!! ; portb = $d301 extra = $4000 ; lda portb pha lda #$00 sta counter ldx #$7f ;Save the ramdisk contents before the test loop1 txa asl ora #$01 sta portb lda extra sta buffer,x dex bpl loop1 ldx #$7f ;Clear tested RAM. loop2 txa asl ora #$01 sta portb lda #$00 sta extra dex bpl loop2 lda #$ff ;Reset PORTB sta portb lda #'K ;Mark base RAM as tested. sta extra ldx #$7f ;Count banks. loop3 txa asl ora #$01 sta portb lda extra bne skip inc counter lda #'K sta extra skip dex bpl loop3 ldx #$7f ;Restore the ramdisk contents loop4 txa asl ora #$01 sta portb lda buffer,x sta extra dex bpl loop4 pla sta portb lda counter rts ; counter .dc 0 ;number of banks buffer .ds 64 ;64-byte buffer Quote Link to comment Share on other sites More sharing options...
ascrnet Posted April 2, 2014 Share Posted April 2, 2014 Hi pab, I liked the idea you're doing a programming language similar to ACTION! but improved. I will be attentive to your language to try it and see how it works. regards Quote Link to comment Share on other sites More sharing options...
Pab Posted April 2, 2014 Author Share Posted April 2, 2014 How obsessive am I about testing this thing? This obsessive. I can report on the newest bank testing and bank switching code testing under... DOS 2.0S - Passed DOS 2.5 - Passed DOS 3 - Passed DOS XL 2.3 - Passed DOS 4 - Passed BWDOS - Passed MyDOS 4.53 - Passed SpartaDOS 3.2 - Would not load into banks SDX 4.46 - Passed Verdict: the language should be able to create programs with code in banked RAM under almost every DOS out there. 1 Quote Link to comment Share on other sites More sharing options...
Pab Posted April 2, 2014 Author Share Posted April 2, 2014 Here is the bank testing code I finally came up with. It takes elements of flashjazzcat's, the Polish routine, and some thoughts of my own. This one avoids the need to shut off interrupts by ignoring bit 0 of PORTB altogether. The value of PORTB on initial call is AND'ed with 1 to isolate that bit, and that setting is OR'ed with the other bits to make sure we don't go swapping the OS in or out at any time. Banks are loaded with test values forwards and checked in reverse, so the highest-valued banks end up at the beginning of the bank table. This guarantees that Bank #1 as referenced by the language is always a stock 130XE's zero bank for maximum compatibility. I intend on testing for SpartaDOS X later on and using their banking table to avoid conflicts. Then the original values are restored. The routine skips FF/FE as a bank possibility because that will always reference the main bank. 10 *= $0480 20 PORTB = $D301 30 NUMBANKS = $C9 ;Number of available banks 40 OLDPORTB = $CA ;Old value of PORTB 50 SAVEMEM = $8E00 60 BANKMEM = $4000 70 BANKTABLE = $EEEE ;Replaced on compile 80 SCRATCH = $D4 90 LDA PORTB 0100 STA OLDPORTB ;Save old value 0110 AND #1 0120 STA SCRATCH ;Save current OSRAM flag 0130 LDX #0 ;Test banks in forward order 0140 LP1 TXA 0150 ASL A 0160 ORA SCRATCH ;Ignore OSRAM bit. 0170 STA PORTB 0180 LDA $4000 0190 STA SAVEMEM,X ;Save current memory 0200 LDA $4001 0210 STA SAVEMEM+$0100,X 0220 TXA 0230 STA $4000 ;Save bank number 0240 EOR #$FF 0250 STA $4001 ;And one's compliment for test. 0260 INX 0270 CPX #$80 ;Only need to test 128 values 0280 BMI LP1 0290 LDX #$7E ;Test backwards to put highest banks 0300 LDY #0 ;in lowest elements in bank table 0310 LP2 TXA ;and skip the main bank (FF) 0320 ASL A 0330 ORA SCRATCH 0340 STA PORTB 0350 TXA 0360 CMP $4000 0370 BNE NOPE ;Not a unique bank. 0380 EOR #$FF 0390 CMP $4001 0400 BNE NOPE 0410 LDA PORTB 0430 STA BANKTABLE,Y 0440 INY 0450 NOPE DEX 0460 BPL LP2 0465 STY NUMBANKS 0470 LDX #$7F 0480 LP3 TXA 0490 ASL A 0500 ORA SCRATCH 0510 STA PORTB 0520 LDA SAVEMEM,X 0530 STA $4000 0540 LDA SAVEMEM+$100,X 0550 STA $4001 0560 DEX 0570 BPL LP3 0580 LDA OLDPORTB 0590 STA PORTB 0600 RTS Quote Link to comment Share on other sites More sharing options...
Pab Posted April 2, 2014 Author Share Posted April 2, 2014 The banking table is located among the program's global variables. If variables are allocated within the code, it will be 9 bytes into the runtime. If variables are allocated elsewhere (through the VARIABLES option in a MODULE statement) then it will be located in that spot. Since the use of banking already required that the first and last modules and their variables not be located in banked RAM, this doesn't cause much of an added restriction. Allocating the bank table with the variables will make it possible to write and compile code for cartridges with the language that will be able to access banked RAM. A compiler switch will be included for those who want to make cartridges to put the testing code into the main portion of the program instead of loaded from disk and INIT'ed. Quote Link to comment Share on other sites More sharing options...
+Stephen Posted April 2, 2014 Share Posted April 2, 2014 How obsessive am I about testing this thing? This obsessive. dos3-a.gif I can report on the newest bank testing and bank switching code testing under... DOS 2.0S - Passed DOS 2.5 - Passed DOS 3 - Passed DOS XL 2.3 - Passed DOS 4 - Passed BWDOS - Passed MyDOS 4.53 - Passed SpartaDOS 3.2 - Would not load into banks SDX 4.46 - Passed Verdict: the language should be able to create programs with code in banked RAM under almost every DOS out there. Nice - I am surprised I immediately recognized the DOS 3 menu Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted April 2, 2014 Share Posted April 2, 2014 (edited) So DOS 3 does work in Altirra now? Troubled by Sparta 3.2 failure: bankload.xex works with this DOS. Are you setting RUNAD? IIRC, Sparta used to otherwise assume run address was start of first segment. Edited April 2, 2014 by flashjazzcat Quote Link to comment Share on other sites More sharing options...
Pab Posted April 2, 2014 Author Share Posted April 2, 2014 Dos 3 does work...if you tell Altirra to emulate an 800XL. If you try it as a 130XE, it dumps you to the self-test instead of loading DOS. I think the problem with Sparta is that it seems to be resetting PORTB after loading a segment, and since my tactic to load directly into a bank is to use an INIT segment to switch banks, then let DOS load into the newly swapped bank, it all ends up going into main RAM. Then when the time comes to run each procedure, BRK-boom. Probably has something to do with the way SD 3.2 used OSRAM buffers, and improper masking of PORTB. Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted April 2, 2014 Share Posted April 2, 2014 Hmmm. All the versions of Sparta 3.x I tested did not reset PORTB. Quote Link to comment Share on other sites More sharing options...
Pab Posted April 2, 2014 Author Share Posted April 2, 2014 (edited) I stepped through it in Altirra to discover exactly what was happening. The previous problems were under 3.2d. For a laugh, I thought I'd try it under 3.2f, and these screencaps are from running under that version. This is after a warm reset, showing the contents of the main bank of RAM after attempting to run the program. The program then runs the bank detection routine, which correctly identifies all banks in the system. The rest of the runtime (such as it is) loads and takes up residence successfully in main RAM. Then the INIT routine switches to bank EF, "bank 1" in its table. After the INIT routine finishes, Sparta goes back into its binary load sequence. The instruction at $076C is the culprit. Which leaves what should be the pristine bank EF as main RAM, which has been written and overwritten by routines. So we cannot binary load directly into banked RAM under SpartaDOS 3.2 (or, I would imagine, 2.x) since they don't bother to mask the current values. I guess they never figured that anyone would want to binary load anywhere but main RAM. So now the question is, do I go back to load-and-move (with more modules and thus more of a slowdown in loading) or do we just say that programs written in whatever-it's-called that use banking for procedures can't be used under SpartaDOS versions before 4.4x? Edited April 2, 2014 by Pab Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted April 2, 2014 Share Posted April 2, 2014 (edited) Well, that's a turn up for the books. Perhaps Gustafson had a few off-days after all. I must have too, since I managed to run my test program with versions of Sparta which didn't exhibit this design flaw (although we shouldn't call it a flaw, since as already said, if direct binary loading into extended banks isn't specified as part of the API, then it's entirely reasonable for the DOS developer not to support it). I'd go for load and move if things are indeed as they appear, and I won't reiterate the numerous reasons for doing so, since I've already explained them all. Slow-downs owing to additional segments and memory moves are completely negligible - again, as already explained. Treat extended banks as you would shadow RAM and the application should be bullet-proof. BTW: Am unable to replicate any problems running DOS 3.0 in Altirra with system set to 65/130XE, 128KB RAM. Edited April 3, 2014 by flashjazzcat Quote Link to comment Share on other sites More sharing options...
Pab Posted April 4, 2014 Author Share Posted April 4, 2014 Well, let's call it an oversight, not a flaw. Thanks to flash's SDX bank test, I've got the bank code for the language working in all configurations possible under Altirra for the XL's and XE's. It doesn't want to work with the expansion schemes for the 800 and 1200XL but I'm not surprised by that. (I would have been more surprised had it worked.) I have one interesting bug to report on, though...but not for my code. DOSKEY for SpartaDOS 4.46 allocates a bank for its command line history, but uses the wrong bank for the purpose! The second bank reported by SDX as being available is actually the one DOSKEY is storing its history in, and writing to it trashes the history. I got an E-mail from my editor that my edits will be arriving late tonight or early tomorrow which is going to severely restrict my free time for the next month or so, so this project will be slowing down a little bit. However, I do hope to have arrays and pointers (the next hurdles) ready by the end of the month, which will leave just objects, floating point, and 32 bit math to tackle before the bootstrap compiler is for most intents and purposes finished. Quote Link to comment Share on other sites More sharing options...
TXG/MNX Posted April 4, 2014 Share Posted April 4, 2014 I the mean while release the compiler as you got it now then people can send bugs they find in the time you not working on the project :-) Quote Link to comment Share on other sites More sharing options...
Pab Posted April 4, 2014 Author Share Posted April 4, 2014 I take back what I said about DOSKEY. Re-working my code. 1 Quote Link to comment Share on other sites More sharing options...
Pab Posted April 4, 2014 Author Share Posted April 4, 2014 Okay, it looks like the bank loading code is now functional and ready to lock down. Methodology decided upon was this: when code is to be loaded into a bank, it is actually loaded into the main bank at the current location of the program counter (after whatever the last routine written or variable allocated, whichever is higher), then a 32-byte relocating program is run from $480 which moves the memory into the banks. If the program counter is in the banking window ($4000-$7FFF) then the code is actually loaded into $8000 and moved from there. Code compiled with this strategy now works under all DOS's tested, including SpartaDOS 3.2. Under all DOS's except SpartaDOS X, a bank testing routine will identify all banks of extended RAM and build an array of those available to be used by the bank switching routines. Under SDX, it will query the DOS to find out which banks are free and only use those. The number of banks available will be stored in memory location $C9, and the actual PORTB value for each bank is irrelevant to the programmer. The language's bank switcher will translate a one-byte value from 1-x into the appropriate PORTB value. Quote Link to comment Share on other sites More sharing options...
Pab Posted April 4, 2014 Author Share Posted April 4, 2014 Since I've started mentioning memory locations used, I might as well post a memory map of Page Zero locations used by the language at this point. $A0 ARGTABLE Arguments passed to procedures and functions. Through $AF $C9 NUMBANKS Number of banks available for programs to work with $CA OLDPORTB PORTB value for the main bank of RAM $CB OP1 Two-byte value (lo in CB high in CC) of first operand in math or move operation $CD OP2 Two-byte value (lo in CD high in CE) of second operand in math or move operation $CF BANK1 Bank to switch to, or banked location of first operand. $D1 BANK2 Banked location of second operand $D4 RES Result of mathematical operation. 16 bits. $D4-$DA are also used periodically for scratch memory, and should not be used by programs. Locations $80 through $9F and $B0 through $C8 are currently unused by the language, and are available for user written programs. $CB through $C1 are generally used internally, but will be documented for inline machine language routines that want to take advantage of the math microruntime package. Quote Link to comment Share on other sites More sharing options...
Pab Posted April 4, 2014 Author Share Posted April 4, 2014 ARGUMENTS TO PROCEDURES AND FUNCTIONS Values passed through arguments are stashed in locations $A0 through $AF. These are then copied into the local variables specified in the procedure definition. If the routine should not store the values locally (for example, inline code that can read $A0-$AF directly) then the compiler switch DEFINE NOARGS can be used. If the procedure or function is a method of an object, the first argument pushed will be a three-byte pointer to the instance of the object that should be worked with. For function calls, the first (or second, if the function is an object method) argument pushed will be a three-byte pointer to the return variable. If there is no return variable (meaning that the result should be discarded) then the pointer will be to $D4:0. String variables as arguments are pushed as three-byte pointers to either the string variable or literal string used in the procedure call. There will be no local string variable created. This means that if you have a definition like PROC WriteString(STRING s) called by WriteString(s3) Then the local variable s will actually be a shadow of the variable s3 used in the call. Quote Link to comment Share on other sites More sharing options...
Pab Posted April 6, 2014 Author Share Posted April 6, 2014 Happy to report that as of this morning, arrays are fully functioning. Just need to tighten up the code to calculate the address of an element. At the moment it's doing a "*1" on byte and character arrays, and I need to special that. 1 Quote Link to comment Share on other sites More sharing options...
Kyle22 Posted October 9, 2014 Share Posted October 9, 2014 Is this project still alive? (I hope) Quote Link to comment Share on other sites More sharing options...
Pab Posted October 10, 2014 Author Share Posted October 10, 2014 Been busy with "paying" work (new novel comes out in February) but have not abandoned the project. Quote Link to comment Share on other sites More sharing options...
Kyle22 Posted October 10, 2014 Share Posted October 10, 2014 Cool, thanks for the update. Quote Link to comment Share on other sites More sharing options...
Pab Posted March 12, 2015 Author Share Posted March 12, 2015 Hello, everyone. Checking in. Work, "paying" writing, and some health concerns had slowed down this project but it's back up to full speed now. Started finding bugs in assigning and referencing array elements, and in the process decided that my variable assignment routines had just become too unwieldy to debug, so I'm breaking them up and rewriting them. After I have this bug sorted out I'm going to post the source I have so far for the PC-side compiler if anyone else wants to play around in it. 4 Quote Link to comment Share on other sites More sharing options...
Pab Posted March 23, 2015 Author Share Posted March 23, 2015 Well, the problems I had been having before having to go work on the novel that now isn't going to come out (grr) have finally been resolved, and as promised I'm posting where I am at the moment. Then I will take a breath and get back to work again. The problems I'd been having had to do with arrays, array references in procedure calls, and function calls as arguments of procedure/function calls. All working now at long last. Coming up next, the compiler as it stands at this moment for those who want to play with it. It is EXTREMELY crude, but source is included. If there are interested parties I may set up a space for it at GitHub or someplace similar so others can join in the fun. Quote Link to comment Share on other sites More sharing options...
Pab Posted March 23, 2015 Author Share Posted March 23, 2015 This archive contains the source code and a Windows (x86 32 bit) executable for the compiler as it stands right now. As I said before, it is still extremely crude. The source code is written in Lazarus, which is an open-source cross-platform development system designed to be compatible with Delphi. If you know Delphi, Lazarus is simple and free to download. The executable version is bloated, I know, because I still have all the debugging information and such still in. WHAT DOESN'T WORK: Floating point variables not fully implemented. Considering dropping them altogether unless there is call to include. Objects/classes and records not fully implemented. This is my next big project. String arrays not yet implemented. Pointers not fully implemented. This is coming shortly. There is no RTL to speak of at this point. I will post the current state of the only RTL routines I've got at this point (mainly for printing) in an upcoming message. WHAT DOES WORK: Loops (FOR, WHILE, UNTIL) Arrays (other than strings) Procedure calls Function calls Bank switching Code stored and run in banked memory Variables stored in banked memory Accomplish Compiler 0.1 pre alpha.zip Quote Link to comment Share on other sites More sharing options...
Pab Posted March 23, 2015 Author Share Posted March 23, 2015 PRINT.ACC - Printing runtime routines // // Accomplish Run-time routines needed for screen output. // // This is a band-aid. The final RTL will have better routines. // PROC StrC(CARD c,STRING POINTER s) // // Return the string representation (decimal) of card c in string "S" // [$A5$A0$85$CB$A5$A1$85$CC$A9$0A$85 $CD$A9$00$85$CE$A9$00$85$AF$20 !DIV $A6$AF$A5$D6$18$69$30$9D$80 $04$E6$AF$A5$D4$85$CB$D0$EB$A5$D5 $85$CC$D0$E5$A5$A2$85$D4$A5$A3$85 $D5$A5$AF$AA$A0$00$91$D4$C8$BD$7F $04$91$D4$CA$D0$F7] RETURN PROC StrB(BYTE b,STRING POINTER s) // // Return the string representation (decimal) of byte b in string "S" // [$A5$A2$85$A3$A5$A1$85$A2$A9 $00$85$A1$4C StrC] END PROC PutD(BYTE ICB,a) // // PUT the byte in a to the specified IOCB number. // [$A5$A0$0A$0A$0A$0A$AA$A9$A1$9D$44 $03$A9$00$9D$45$03$A9$01$9D$48$03 $A9$00$9D$49$03$A9$0B$9D$42$03$20 $56$E4] RETURN PROC PrintD(BYTE ICB, STRING s) // // Print string to specified IOCB // [$A5$A0$0A$0A$0A$0A$AA$A5$A1$85$D4 $9D$44$03$FE$44$03$A5$A2$85$D5$9D $45$03$A9$0B$9D$42$03$A0$00$B1$D4 $9D$48$03$20$56$E4] RETURN PROC PrintDE(BYTE ICB, STRING s) // // Print string to IOCB, followed by EOL. // [$20 PrintD $A9$9B$85$A1$4C PutD] END PROC Print(STRING POINTER s) // // Print string to IOCB #0 // [$A5$A2$85$A3$A5$A1$85$A2$A5$A0$85 $A1$A9$00$85$A0$4C PrintD] END PROC PrintE(STRING POINTER s) // // Print string to IOCB #0 followed by EOL. // [$20 Print $A9$00$85$A0$A9$9B$85 $A1$4C PutD] END PROC PrintC(CARD c) // // Print CARD to IOCB #0 // STRING str=$580 StrC(c,str) Print(str) RETURN PROC PrintCE(CARD c) // // Print CARD to IOCB #0 followed by EOL. // STRING str=$580 StrC(c,str) PrintE(str) RETURN PROC PrintB(BYTE b) // // Print BYTE to IOCB #0 // STRING str=$580 StrB(b,str) Print(str) RETURN PROC PrintBE(BYTE b) // // Print BYTE to IOCB #0 followed by EOL. // STRING str=$580 StrB(b,str) PrintE(str) RETURN 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.