RXB Posted February 21, 2023 Share Posted February 21, 2023 17 minutes ago, senior_falcon said: In my example, 10 CALL LOAD(-2,3), you did not give your opinion as to whether the value 3 is placed at >FFFE. I am not sure whether you believe that or not, but most people who use the TI would think so, and certainly a few moments using a debugger would inevitably lead you to that opinion. When I use a word processor, I have noticed that every time I press the "A" key that an A appears on the screen. If some jackwad then comes along and said "LOL, show me the code for that?" what would you think about that person. This is GPL for CALL LOAD: *********************************************************** * ASSEMBLY LANGUAGE SUPPORT FOR 99/4 * * LOAD, INIT, PEEK, LINK, CHARPAT JDH 08/21/80 *********************************************************** * FORMAT FOR LOAD: * CALL LOAD open load-directive (comma load-directive) * close * load-directive = file-name / address (comma data) * (null / file-name) * file-name = string-expression * address = numeric-expression * data = numeric-expression * * FILE TYPE = FIXED 80, DISPLAY , SEQUENTIAL FILE * * FUNCTION: * LOADS ASSEMBLY LANGUAGE CODE INTO EXPANSION RAM * ADDRESSES: >2000 - >>3FFF RELOCATING * RELOCATABLE CODE INTO AVAILABLE MEMORY, ABSOLUTE CODE * IS LOADED * INTO ITS ABSOLUTE ADDRESS, ENTRY POINTS ARE DEFINED BY * 'DEF' STATEMENTS, AND ARE LOADED INTO HIGH END OF ERAM * * RELOACATABLE OR ABSOLUTE CODE MAY BE STORED ON A FILE * 9900 OBJECT CODE FORMAT. * VALID TAGS = 0, 5, 6, 7, 9, A, B, C, F,: * TAGS 1, 2, I, M, ARE IGNORED * THE SYMT OPTION IS NOT SUPPORTED. * ABSOLUTE CODE MAY BE LOADED DIRECTLY FROM PROGRAM * BY SPECIFYING AN ADDRESS INSTEAD OF A FILE NAME, * FOLLOWED BY THE DATA TO BE LOADED (WHICH IS PUT IN THE * RANGE 0 to 255 * THE RANGE OF THE ADDRESS OR DATA IS LIMITED TO * 32767 to -32768 * MULTIPLE DIRECT LOADS CAN BE IN THE SAME LOAD COMMAND * PROVIDED THEY ARE SEPARATED BY EITHER A FILENAME OR A * NULL STRING. * * RXB CHANGED MVUP TO GPL MOVE AS MOVING 2 BYTES USING 14 * BYTES OF GPL TO MOVE RAM TO SCRATCH PAD WAS SLOWER. * * MVUP WAS USED TO TRANSFER DATA FROM CPU RAM TO ERAM * SINCE IT WAS NOT KNOWN AT FIRST THAT THE MOVE * INSTRUCTION COULD TRANSFER FROM CPU RAM TO ERAM * (PROVIDED THAT >8300 IS SUBTRACTED FROM THE ADDRESSES) *********************************************************** * RXB PATCH CHANGED CALL INIT TO ROM 3 * REPLACING ORIGINAL TO ASSEMBY IN 1 CHUNK *********************************************************** * RXB BRANCH TABLE FOR LONG GROMS * >C010 was CALL LINK *********************************************************** * CALL LOAD("DSK#.FILENAME"[,...]) * * CALL LOAD(ADDRESS,LIST[,...]) * *********************************************************** LOAD DST >0001,@CHKSUM {INITIALIZE FILE FLAG} * GKXB Change load routine. Delete check for INIT * add to clear flag bits. CALL GKLOAD LPD0 CEQ LPARZ,@CHAT SYNTAX ERROR if no "(" BR ERRSY1 XML PGMCHR Skip over * MAIN PARESE LOOP * * Check for file-name or address LDP1 XML PARSE BYTE RPARZ * PARSE up to ")" or "," CEQ STRING,@FAC2 Process file name BS LDP2 * Otherwise it is an address * Convert address to integer, save in @PC XML CFI Convert FAC to integer CEQ 3,@FAC10 Check for overflow BS ERRN01 DST @FAC,@PC Save in ERAM location pointer * Check for "," if there then data should folow * else end of load statement, goto LDP5 LDP4 CEQ COMMAZ,@CHAT BR LDP5 * DATA follows or a STRING if no more data XML PGMCHR Skip "," XML PARSE Get data value or string if * end of data BYTE RPARZ * Parse up to ")" or "," CEQ STRING,@FAC2 No more data BS LDP2 * FAC contains a numeric XML CFI FAC to INTEGER CEQ 3,@FAC10 Check for overflow BS ERRN01 * GKXB Code for CPU write moved to LOADDT. Add code to * check VDP or GRAM bits and write to VDP. CLOG >08,@GKFLAG Check VDP bit BS LDGRAM No, check GRAM bit ST @FAC1,V*PC Yes, write to VDP DINC @PC Point to next byte B LDP4 Continue with LOAD routine * GROM ADDRESS >C088 FOR LDP5 * Check for ")" IF there return ELSE SYNTAX ERROR LDP5 CEQ RPARZ,@CHAT Return BS LDRET B ERRSY1 SYNTAX ERROR * LDP2 * Process file name LDP2 CZ @FAC7 Check for null string BS LDNE2 * GKXB Change 'LOAD FILE' to check for INIT CALL GKINIT *************** LOAD DATA INTO ERAM *********************** * LOAD FRESTA, FREEND from ERAM DST FSLOC,@VARB Source DST FRESTA,@PAD Destination DST 4,@ARG # of bytes to move XML MVUP Load * Initialize PC, OFFSET in case of no "0" tag DST @FRESTA,@PC DST @FRESTA,@OFFADD Base address for load module * Read in one record, evaluate the TAG field * LDRD - LDTG LDRD DST 0,@CHKSUM Clear check sum CALL READIT Rear in a record LDTG MOVE 5,V*BUFPNT,@TAG Get TAG & field CALL LDIPCS Add 5 to BUFPNT, add ASCII BYTE 5 * Value of chars. Read to check * Convert @FIELD to numeric (from ASCII hex value) * Store result: HIGH BYTE to FIELD, LOW BYTE to FIELD+1 * Convert HIGH BYTE first: @FIELD & @FIELD+1 * Store result in field SUB >30,@FIELD >30 = "0" CGT 9,@FIELD Subtract ASCII difference * between "9" and "A" BR GC0C7 SUB 7,@FIELD GC0C7 SLL 4,@FIELD FIELD=FILED*32 SUB >30,@FIELD+1 CGT 9,@FIELD+1 BR GC0D5 SUB 7,@FIELD+1 GC0D5 ADD @FIELD+1,@FIELD Add to HIGH BYTE * Now convert LOW BYTE: @FIELD+2 & @FIELD+3 * Store result in LOW BYTE of FIELD to FIELD+1 SUB >30,@FIELD+2 CGT 9,@FIELD+2 BR GC0E3 SUB 7,@FIELD+2 GC0E3 ST @FIELD+2,@FIELD+1 Store in LOW byte of result SLL 4,@FIELD+1 FIELD+1 = FIELD+1*32 SUB >30,@FIELD+3 CGT 9,@FIELD+3 BR GC0F4 SUB 7,@FIELD+3 GC0F4 ADD @FIELD+3,@FIELD+1 Add to low byte * Branch to evaluation procedure for TAG SUB >30,@TAG >30 = "0" CGE 0,@TAG If TAG < "0" ILLEGAL CHAR BR ERRUC1 CGT >0A,@TAG TAGS "0" to ":" BS GC11C CASE @TAG BR TAG0 "0" RELOCATABLE LENGTH BR LDTG IGNORE "1" TAG BR LDTG IGNORE "2" TAG BR ERRUC1 No external REF "3" BR ERRUC1 No external REF "4" BR TAG5 "5" relocatable entry DEF BR TAG6 "6" Absolute entry DEF BR TAG7 "7" check sum BR LDTG "8" ignore check sum BR TAG9 "9" Absolute LOAD address BR LDDNE ":" end of file GC11C SUB >11,@TAG Subtract offset so * that "A" is =0 CGE 0,@TAG ";" to "@" illegal char BR ERRUC1 * Skip over "I" tag - 8 char, program ID that follows CEQ 8,@TAG BS LDTG2 * Skip over "M" TAG -10 char, program ID that follows CEQ 12,@TAG BR LDTG3 CALL LDIPCS BYTE 10 B LDTG LDTG3 CGT 5,@TAG TAGS "G" are legal BS ERRUC1 CASE @TAG BR TAGA "A" RELOCATABLE PROGRAM ADDRE BR TAGB "B" ABSOLUTE VALUE BR TAGC "C" RELATIVE ADDRESS BR ERRUC1 "D" ERROR BR ERRUC1 "E" ERROR - UNDEFINED BR LDRD "F" END OF RECORD * TAG0 to TAGB * EVALUATE TAG FIELDS TAG0 DST @FRESTA,@OFFADD NEW BASE ADDRESS DST @FRESTA,@PC NEW PC DADD @FIELD,@FRESTA ADD LENGTH TO FIND END OF * RELOCATABLE PROGRAM WHICH IS * START OF NEXT PROGRAM * Make sure we won't run into routine name table now, so we * don't have to check every time we load a value into ERAM * routine table must make sure it doesn't run into * relocatable assembly language code through. DCHE @FREEND,@FRESTA OUT OF MEMORY BS ERRMF1 * SKIP OVER PROGRAM ID - 8 BYTES LDTG2 CALL LDIPCS BYTE 8 * INC BUFPNT, COMPUTE CHECKSUM B LDTG TAG5 DADD @OFFADD,@FIELD Add starting offset * TAG6 is an absolute address so do not need to add offset TAG6 MOVE 6,V*BUFPNT,@INDEX Get symbol name CALL LDIPCS INC BUPNT, COMPUT CHECKSUM BYTE 6 * We read 6 chars * Add symbol and its address - stopped in field - to the * routine entry table. It is put at the end of the table * (the end of the table is towards the low end of memory) * Since the table is searched from the end first, if there * are any duplicate labels the last one entered will have * precedence over the early one(s). DDECT @FREEND Set to address field * Load address (stored in field in CPU RAM) into routine * Name table which is in expansion RAM DST FIELD,@VARB Source DST @FREEND,@PAD Destination DST 2,@ARG # bytes to move XML MVUP CPUR RAM to ERAM * Load symbol into routine name table DSUB 6,@FREEND Set to symbol field DST INDEX,@VARB Source DST @FREEND,@PAD Destination DST 6,@ARG Move 6 bytes XML MVUP CPU RAM to ERAM * Check to see if we've run into assembly language code DCHE @FREEND,@FRESTA Out of memory BS ERRMF1 B LDTG If not then continue *********************************************************** * ROUTINE NAME TABLE ENTRY * * 0 1 2 3 4 5 6 7 * ----------------------------------- * FREEND | S | Y | M | B | O | L | ADDRESS | * (AFTER ENTRY) ----------------------------------- * FREEND | | | | | | | | * (BEFORE ENTRY) ----------------------------------- * * FREEND is initialized to >4000 by INIT, address is at * a higher memory location then symbol *********************************************************** TAG7 DNEG @FIELD Checksum is 1's compelement DCEQ @FIELD,@CHKSUM Check sum error BR ERRDE1 B LDTG TAGA DADD @OFFADD,@FIELD PC = OFFADD ^ FIELD * TAG 9 is an absolute address so no need to add offset TAG9 DST @FIELD,@PC B LDTG TAGC DADD @OFFADD,@FIELD * TAG B is an absolute entry so no need to add offset * Relocatable code is checked to see if it will run into * is no need to check now. Absolute code can go anywhere. * * Load field into expansion RAM using MVUP routine TAGB DST @PC,@PAD Destination DST FIELD,@VARB Source DST 2,@ARG Move 2 bytes XML MVUP CPU RAM to ERAM DINCT @PC We loaded 2 bytes B LDTG ********* END OF LOAD FOR CURRENT FILE ******************** * * FRESTA & FREEND are stored in CPU RAM (>8308) * While loading a file into expansion RAM. * So if the values of FRESTA or FREEND are to be changed * then word locations >8308 and >830A must be changed and * not expansion RAM. * * LDDNE - LDNE2 * * DONE WITH LOAD * Put FRESTA, FREEND back into expansion RAM * If FRESTA is odd then make it even * so that the next program starts on an even boundry LDDNE CLOG 1,@FRESTA+1 Low byte odd? BS GC1C1 DINC @FRESTA Force to next even boundry GC1C1 DST FRESTA,@VARB Source DST FSLOC,@PAD Destination DST 4,@ARG Load 4 bytes XML MVUP CPU RAM to ERAM CALL CLSIT Close file * Check for end of load command ")" LDNE2 CEQ RPARZ,@CHAT Check for ")" BS LDRET CEQ COMMAZ,@CHAT Syntax error BR ERRSY1 XML PGMCHR Skip comma B LDP1 Continue in main loop *************** LDRET - LDRET2 **************************** * * Return to calling routine LDRET XML PGMCHR Skip over * Entry point for INIT LDRET2 CALL CHKEND Check for end of statement BR ERRSY1 If not end then syntax error CALL RETURN Return to caller ********************** CHKIN ****************************** * Check for INIT-FLAG = >AA55 * MOVE ERAM(INITF) to CPU *FAC PAGE EQU $ CHKIN DCEQ >AA55,@INITF *** RXB REPLACEMENT ROUTINE **** BR ERRSYN * SYNTAX ERROR * No files have been opened so if there is a syntax error * goto ERRSYN! RTN * RETURN TO CALLING ROUTINE *********************** FILE ROUTINES ********************* *********************************************************** * INCREMENT BUFFER POINTER by value after call statement * ADD VALUES READ TO CHECKSUM unless the first character * is a "7" = >37 , then add only "7" character to checksum * (other value is the checksum) * *************************** LDIPCS ************************ LDIPCS FETCH @INDEXC Index = # of bytes read CEQ >37,V*BUFPNT BR GC213 DADD >0037,@CHKSUM Add value of "7" to checksum DADD 5,@BUFPNT 1 for "7", 4 for checksum B GC224 GC213 ST V*BUFPNT,@FAC1 Convert to 2 byte value CLR @FAC ----------------------------- DADD @FAC,@CHKSUM Add char to checksum DINC @BUFPNT DEC @INDEXC Do it index # of times CZ @INDEXC BR GC213 GC224 RTN ********************** OPENIT ***************************** OPENIT DST @FAC6,@BYTES Store actual spec length DADD PABLEN+80,@BYTES Add in the PAB length and * buffer length XML VPUSH Push possible temp string XML GETSTR and try to allocate space XML VPOP Restore original string data * * THE FOLLOWING VARIABLES CONTAIN IMPORTANT INFO * * FAC4, FAC5 Start address of original device specific * FAC6, FAC7 Length of original device specifications * SREF Location of PAB in VDP memory * BYTES Length of entire PAB including specificat MOVE @FAC6,V*FAC4,V@PABLEN(@SREF) * Device pathname CLR V*SREF Clear the entire PAB MOVE PABLEN-1,V*SREF,V@1(@SREF) * Clear PAB ST @FAC7,V@NLEN(@SREF) Copy specifications length ST >60,V@SCR(@SREF) Screen offset ST 4,V@FLG(@SREF) Dis, fix, seq, input DADD @SREF,@FAC6 Calculate the address of DADD PABLEN,@FAC6 the buffer DST @FAC6,V@BUF(@SREF) Store buffer address in PAB CALL DSRCAL RTN *********************************************************** READIT DST V@BUF(@SREF),@BUFPNT INIT buffer pointer ST 2,V*SREF ST V@LEN(@SREF),V@CHRCNT(@SREF) CALL DSRCAL RTN ************************* CLSIT *************************** CLSIT ST 1,V*SREF Prepare to close ******************** DSRCAL - DSKERR ********************** DSRCAL DST @SREF,@FAC12 Compute start address of spec DADD NLEN,@FAC12 Ready to call DSR routine CALL LINK Call DSR thourgh program link BYTE 8 * Type = DSR (8) BS DSKERR Couldn't find the DSR CLOG >E0,V@FLG(@SREF) Set condition bit if no error BR DSKERR RTN DSKERR DST @FREPTR,@PABPTR Set up dummy PAB DSUB 6,@PABPTR Make it standard size DST V*SREF,V@4(@PABPTR) Store error code CALL CLSNOE Close File CALL ERRZZ Issue I/O error BYTE 36 * ********************** CLSNOE ***************************** * Try to close the current file * Ignore any errors from the closing of the file. * Since the PAB is not in the normal PAB list * then we have to close the file in the load routine. * ERRZZ will close the rest of the files. * ** CLOSE IT ONLY IF IT HAS BEEN OPENED CLSNOE DCEQ 1,@CHKSUM Check file flag BS GC2B9 ST 1,V*SREF Store close file code DST @SREF,@FAC12 Compute start address of spec DADD NLEN,@FAC12 Ready to CALL DSR CALL LINK CALL DSR through program link BYTE 8 * "8" is type of DSR GC2B9 RTN *********************************************************** * INIT JDH 9/02/80 *********************************************************** * CALL INIT * *********************************************************** * Check if expansion RAM present * Load support into expansion RAM from GROM INIT CZ @RAMTOP If no ERAM, SYNTAX ERROR BS ERRSYN ** Load Assembly header, support routines ** * GKXB Correct INIT routine. CLR @>6004 * Set ROM PAGE 3 at >6004 XML CINIT * Move from ROM 3 to RAM B ECRTN * RXB custom return routine *********************************************************** You will notice there is nowhere that decimal integer is allowed. If you look at XB token code of CALL LOAD(-2,3) in Classic99 debugger at >FFD0 is: 10 CALL LOAD(-2,3) 00 00 0A FF D6 12 9D C8 04 4C 4F 41 44 B7 C2 C8 01 32 B3 C8 01 33 B6 00 l L O A D ( - n l 2 , n l 3 ) e e u e u e n n m n m n d g e g e g t r t r t h i h i h c c This is the code that XML PARSE fetches from XB and as you can see it does what I have said all along. 00 0A is 0010 the line number. 04 and 01 and 01 are length of LOAD or number of digits of any number in character format. B7 is token for ( character C2 is minus sign in token character C8 is token for a number to follow in character token format. 32 is token for 2 character B3 is token for comma character 33 is token for 3 character B6 is token for ) character Thus this is the XB token format of XB programs for this line 10 CALL LOAD(-2,3) and this kind of maintains the original source. I guess you could say the 2 and 3 are integers but as they are converted to token format so humans can see the source there is a reason to maintain the original source as typed in, but that is not how XB works. It seems the confusion you guys have is you do not understand the token format and why it exists in first place for the Interpeter. Quote Link to comment Share on other sites More sharing options...
RXB Posted February 21, 2023 Share Posted February 21, 2023 54 minutes ago, apersson850 said: I'm waiting... Read what I wrote to Senior_falcon Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted February 21, 2023 Share Posted February 21, 2023 (edited) 2 hours ago, RXB said: Thus this is the XB token format of XB programs for this line 10 CALL LOAD(-2,3) and this kind of maintains the original source. I guess you could say the 2 and 3 are integers but as they are converted to token format so humans can see the source there is a reason to maintain the original source as typed in, but that is not how XB works. It seems the confusion you guys have is you do not understand the token format and why it exists in first place for the Interpeter. I think it would be safe to say that someone who could write a compiler for Extended BASIC would have a good working knowledge of how the XB lines are tokenized, and why. It sure sounds like you do not believe that after CALL LOAD(-2,3), the value 3, or >03, or 00000011 is stored at memory location >FFFE. Hard to believe you might think that, but you are entitled to your (erroneous) opinion. I feel like one of those unfortunate animals trapped in the La Brea tar pit. You struggle valiantly, but as you become mired deeper and deeper in the tar, you finally get worn down and at the end you finally accept there is nothing more you can do, and realizing that, you close your eyes and await.....oblivion. Edited February 21, 2023 by senior_falcon 3 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 21, 2023 Share Posted February 21, 2023 35 minutes ago, senior_falcon said: I feel like one of those unfortunate animals trapped in the La Brea tar pit. You struggle valiantly, but as you become mired deeper and deeper in the tar, you finally get worn down and at the end you finally accept there is nothing more you can do, and realizing that, you close your eyes and await.....oblivion. If you have any lives left, don't go near the tar pit again. 5 Quote Link to comment Share on other sites More sharing options...
Retrospect Posted February 21, 2023 Share Posted February 21, 2023 @retrodroid I was reading an interview from the early 80's with John C Plaster, the author of Tombstone City , the educational cartridges and Chisholm Trail. It's well known that Tombstone City / Saguaro City was one of the games that was created using an actual TI99 rather than the 990 minicomputer and emulation. During the interview he stated that he had most of the game running by May '81. That tells us that the poor guy was using the 99/4 and not the 99/4A ... so he's done well there, written it all out in Assembly and used the calculator keyboard of the 99/4 to type on! He said that learning the 9900 assembly wasn't difficult, but then again he was a master at mathematics. He must have been loading the Editor Assembler from cartridge and storing his code on disks, and most likely drawing out his graphics on graph paper with pencils and a rubber. Then when we read about how Parsec was developed that's fascinating also - they did use a kind of prehistoric "magellan" in ways ... to do the graphics for the tumbling asteroids they used TI Logo and had it churn out the Hex codes for the patterns onto a disk. I'd LOVE to have the same abilities with Assembly as the guys who made the original games. 3 Quote Link to comment Share on other sites More sharing options...
RXB Posted February 21, 2023 Share Posted February 21, 2023 1 hour ago, senior_falcon said: I think it would be safe to say that someone who could write a compiler for Extended BASIC would have a good working knowledge of how the XB lines are tokenized, and why. It sure sounds like you do not believe that after CALL LOAD(-2,3), the value 3, or >03, or 00000011 is stored at memory location >FFFE. Hard to believe you might think that, but you are entitled to your (erroneous) opinion. I feel like one of those unfortunate animals trapped in the La Brea tar pit. You struggle valiantly, but as you become mired deeper and deeper in the tar, you finally get worn down and at the end you finally accept there is nothing more you can do, and realizing that, you close your eyes and await.....oblivion. As they are single byte values only, that does not change anything on how I said they got there from the XML PARSE as this routine is XB ROM Now I can say you are right about values at >FFFE with 3 being there but that is due to XML CFI is in ROM 0 not anywhere in XB ROM or GPL. The exact place is at >0682 in ROM 0 that line that says: MOVB 11,*R2+ this is called from XML CFI which is a ROM 0 routine at >12B8 This line puts 3 at >FFFE or if you add in more values into CALL LOAD(-2,3,4,5) would put 3 at >FFFE, 4 at >FFFD, and 5 at >FFFE I stand corrected and I am mistaken as to why they are there, but everything else I said is true after all none of this is XB at all is it? The routine uses an EQU to call CFI in ROM 0, again not in any GPL or XB ROM. You are right about >FFFE being byte values I stand corrected on that. P.S. I have no clue why it would put these values there as they have no location in symbol tables so how would you find or use them? If you add line 5 X=3 and 10 CALL LOAD(-2,X) you will find at >FFC0 the floating-point number >40 03 00 00 00 00 00 00 and the X is in the symbol table pointing to it. Honestly it looks like those bytes at >FFFE are totally useless to XB as a side effect of ROM 0 Quote Link to comment Share on other sites More sharing options...
Retrospect Posted February 21, 2023 Share Posted February 21, 2023 At least this argument you're both having is an educational one. Some people will learn from this. Not me though I'm clueless as usual. Quote Link to comment Share on other sites More sharing options...
RXB Posted February 21, 2023 Share Posted February 21, 2023 7 minutes ago, Retrospect said: At least this argument you're both having is an educational one. Some people will learn from this. Not me though I'm clueless as usual. Yes you are very correct, I did learn something from this and took all day doing research on it. And no you are a really smart guy as far as I can tell. 1 Quote Link to comment Share on other sites More sharing options...
Retrospect Posted February 22, 2023 Share Posted February 22, 2023 7 minutes ago, RXB said: Yes you are very correct, I did learn something from this and took all day doing research on it. And no you are a really smart guy as far as I can tell. Thanks. I do okay in the my own field. I can't say I'm smart though. Just winging it. You guys are the real intelligent ones. Yourself, Falcon, and others. I just create fantastic arcade games 2 Quote Link to comment Share on other sites More sharing options...
retrodroid Posted February 22, 2023 Share Posted February 22, 2023 (edited) I have newbie questions regarding the best way to debug my AL code. Currently, when something doesn't immediately work the way I intended (2/3 of the time it seems), I fire up the Classic99 Debugger, and usually I'll use a technique like moving a known value or values into R14 at the locations where I want to set a breakpoint. So say step 1, LI R14,>AAAA a little further down, LI R14, >BBBB. Then I set a breakpoint with R14 for either of those values, examine the other CPU registers at that point, and try to glean why they don't contain the nice neat values I am expecting. With this technique I can also resume execution for another cycle, etc. to see how things unfold a bit. It basically works, but is it time-consuming and very simplistic. What I would *like* to be able to do, is follow the source AL files as it executes, have all the referenced memory locations in the current source line shown so I can see the memory contents of everything being read or written, beyond the registers, without having to figure out what the resolved memory addresses are for each thing myself. Is there a debugger out there that can do that? Barring that, what are the best practices for debugging AL that you all use? Are there any tutorials or other reference material available? Edited February 22, 2023 by retrodroid 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 22, 2023 Share Posted February 22, 2023 54 minutes ago, retrodroid said: I have newbie questions regarding the best way to debug my AL code. Currently, when something doesn't immediately work the way I intended (2/3 of the time it seems), I fire up the Classic99 Debugger, and usually I'll use a technique like moving a known value or values into R14 at the locations where I want to set a breakpoint. So say step 1, LI R14,>AAAA a little further down, LI R14, >BBBB. Then I set a breakpoint with R14 for either of those values, examine the other CPU registers at that point, and try to glean why they don't contain the nice neat values I am expecting. With this technique I can also resume execution for another cycle, etc. to see how things unfold a bit. It basically works, but is it time-consuming and very simplistic. What I would *like* to be able to do, is follow the source AL files as it executes, have all the referenced memory locations in the current source line shown so I can see the memory contents of everything being read or written, beyond the registers, without having to figure out what the resolved memory addresses are for each thing myself. Is there a debugger out there that can do that? Barring that, what are the best practices for debugging AL that you all use? Are there any tutorials or other reference material available? With those nice break points installed switch classic99 to the Disasm view . After each break point just press F2 to single step the code one instruction at a time. Press F1 to run to the next break-point It's awesome. 2 2 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted February 22, 2023 Share Posted February 22, 2023 55 minutes ago, retrodroid said: Barring that, what are the best practices for debugging AL that you all use? Are there any tutorials or other reference material available? Are you writing support routines for XB, or stand alone assembly programs? 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted February 22, 2023 Share Posted February 22, 2023 (edited) 1 hour ago, TheBF said: With those nice break points installed switch classic99 to the Disasm view . After each break point just press F2 to single step the code one instruction at a time. Press F1 to run to the next break-point It's awesome. What he said. One thing TheBF omitted is that you can press F3 when you are at a subroutine like BLWP @VMBW or BL @MYSUB. This will do the subroutine and come back to the next line of your code. Finding the break points. Let's say you want to set a break point at 3 places in your code: LOOP1, LOOP2, and SETREG Find an unused part of memory. Let's say you know >B000 is safe. AORG >B000 DATA LOOP1 DATA LOOP2 DATA SETREG RORG In my first post I forgot this. Now when you load the assembly code you can use the debugger to look at >B000 and there you will find the addresses for LOOP1, LOOP2, and SETREG If LOOP1 is >3456 you can set a breakpoint to it with *3456 which breaks whenever activity happens there. <3456 breaks when that address is read from, so that is probably even better, but I got in the habit of doing it the other way. Edited February 22, 2023 by senior_falcon 3 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 22, 2023 Share Posted February 22, 2023 10 hours ago, RXB said: I stand corrected and I am mistaken as to why they are there, but everything else I said is true after all none of this is XB at all is it? P.S. I have no clue why it would put these values there as they have no location in symbol tables so how would you find or use them? If you add line 5 X=3 and 10 CALL LOAD(-2,X) you will find at >FFC0 the floating-point number >40 03 00 00 00 00 00 00 and the X is in the symbol table pointing to it. Honestly it looks like those bytes at >FFFE are totally useless to XB as a side effect of ROM 0 It doesn't matter if it's Extended BASIC or something else. It just has to make an integer of the address and data, and out of the data it uses only eight bits at a time, or it would not work. It also doesn't matter if Extended BASIC calls CFI in the console's ROM or does it by itself. It still happens on Extended BASIC's behalf. The CALL LOAD(-2,3) is just an example. You can pick any address. The principle is the same. But to find it again you can use CALL PEEK, of course. 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 22, 2023 Share Posted February 22, 2023 9 hours ago, retrodroid said: Barring that, what are the best practices for debugging AL that you all use? Now I haven't done much of that in recent years. But the emulators are of course fantastic, compared to what we had when it was the machine itself only. It's more like what they had at TI when they used their TI 990 computers for development. Back in the days I had two favorite tools for debugging. The Hewlett-Packard HP 16C. Since it's a calculator that can handle binary math and also is programmable, you could enter your algorithms as a program on it and test them. You can set the word size to 16 bits and use the registers to emulate the TMS 9900 on it. It even has double multiply and divide, which works just like MPY and DIV. The Explorer program from Miller's graphics. It allows you to test at least sections of your programs in an emulated way, where you can see everything happening on the screen. Now I mainly wrote assembly programs for use with the p-system. There the best way was to write the program in Pascal first, then convert that to assembly, once I was convinced there was nothing wrong with the structure of the program itself. That worked as long as I could do what I needed to do from Pascal. 2 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted February 22, 2023 Share Posted February 22, 2023 12 hours ago, Retrospect said: He must have been loading the Editor Assembler from cartridge and storing his code on disks, and most likely drawing out his graphics on graph paper with pencils and a rubber. I still use rubber - and a mask - a bitmask of course. 💥 1 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted February 22, 2023 Share Posted February 22, 2023 11 hours ago, Retrospect said: Just winging it. We all do. 😋 1 Quote Link to comment Share on other sites More sharing options...
retrodroid Posted February 22, 2023 Share Posted February 22, 2023 13 hours ago, TheBF said: With those nice break points installed switch classic99 to the Disasm view . After each break point just press F2 to single step the code one instruction at a time. Press F1 to run to the next break-point It's awesome. Wow - not sure how I missed that! I'm always just trying to get my "thing" working and not spending enough time exploring a bit more. On that note, what are the "Bug99 Window" and "Heatmap" options in Classic99 for? I've tried them but neither shows anything. 12 hours ago, senior_falcon said: What he said. One thing TheBF omitted is that you can press F3 when you are at a subroutine like BLWP @VMBW or BL @MYSUB. This will do the subroutine and come back to the next line of your code. Finding the break points. Let's say you want to set a break point at 3 places in your code: LOOP1, LOOP2, and SETREG Find an unused part of memory. Let's say you know >B000 is safe. AORG >B000 DATA LOOP1 DATA LOOP2 DATA SETREG RORG In my first post I forgot this. Now when you load the assembly code you can use the debugger to look at >B000 and there you will find the addresses for LOOP1, LOOP2, and SETREG If LOOP1 is >3456 you can set a breakpoint to it with *3456 which breaks whenever activity happens there. <3456 breaks when that address is read from, so that is probably even better, but I got in the habit of doing it the other way. Nice! Will certainly keep this in my back pocket. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 22, 2023 Share Posted February 22, 2023 51 minutes ago, retrodroid said: Wow - not sure how I missed that! I'm always just trying to get my "thing" working and not spending enough time exploring a bit more. On that note, what are the "Bug99 Window" and "Heatmap" options in Classic99 for? I've tried them but neither shows anything. Bug99 is Thierry Nouspikel’s debugger. The Bugg99 window and Heatmap are discussed in the Classic99 manual, which is available through this option: ...lee 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted February 22, 2023 Share Posted February 22, 2023 1 minute ago, Lee Stewart said: The Bugg99 window and Heatmap are discussed in the Classic99 manual, which is available through this option: Ah yes, the dreaded words we all hate to hear. RTFM. 3 Quote Link to comment Share on other sites More sharing options...
retrodroid Posted February 22, 2023 Share Posted February 22, 2023 3 hours ago, Lee Stewart said: Bug99 is Thierry Nouspikel’s debugger. The Bugg99 window and Heatmap are discussed in the Classic99 manual, which is available through this option: ...lee 3 hours ago, senior_falcon said: Ah yes, the dreaded words we all hate to hear. RTFM. Indeed! Actually, I did try that but I'm running a one-off build of Classic99_64.exe on Wine, on an M2 mac, so it didn't work. ...so then I dug through the wine "C" drive and found a copy of it there. Interestingly, Memory Map doesn't render at all with my config. I will review the Debug section - no doubt a wise time investment. Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted February 26, 2023 Share Posted February 26, 2023 On 2/22/2023 at 1:29 AM, retrodroid said: I have newbie questions regarding the best way to debug my AL code. Currently, when something doesn't immediately work the way I intended (2/3 of the time it seems), I fire up the Classic99 Debugger, and usually I'll use a technique like moving a known value or values into R14 at the locations where I want to set a breakpoint. So say step 1, LI R14,>AAAA a little further down, LI R14, >BBBB. Then I set a breakpoint with R14 for either of those values, examine the other CPU registers at that point, and try to glean why they don't contain the nice neat values I am expecting. With this technique I can also resume execution for another cycle, etc. to see how things unfold a bit. It basically works, but is it time-consuming and very simplistic. What I would *like* to be able to do, is follow the source AL files as it executes, have all the referenced memory locations in the current source line shown so I can see the memory contents of everything being read or written, beyond the registers, without having to figure out what the resolved memory addresses are for each thing myself. Is there a debugger out there that can do that? Barring that, what are the best practices for debugging AL that you all use? Are there any tutorials or other reference material available? The js99er debugger is not on par with the debugger in classic99, but it does offer the possibility to load a listing file generated by xas99. With that you basically can follow the source AL file. Oh and with classic99 you can include some dummy opcodes as data statements that allow you to log the values of memory locations to the debugger log. That comes in very handy as well. Used that a couple of times while working on stevie, my programming editor. 4 Quote Link to comment Share on other sites More sharing options...
retrodroid Posted February 28, 2023 Share Posted February 28, 2023 (edited) Folks, I'm really pleased with my progress thus far. I have all of my player-movement types and animations implemented and tuned and it plays like a dream. I also have a basic screen-navigation scheme working so I can run and jump and climb and fall my way through a small initial map of different screens. There have been many difficult days where the simplest code just wouldn't do what it was "supposed" to, but I've worked through them (with some of your help) and am at a point where my basic game loop is working really well. I'm also finding that small tweaks are amazingly simple to implement now, with everything being managed at a per-frame level (actually, intra-frame because of my approach to implementing velocity). I've even gone back and optimized certain routines that were a bit sloppy with the CPU and realized significant gains. It's been a very rewarding experience. I'm now ready to refactor my code to run off a cart (been using E/A option #3 to load and run until now), and the "reality cheque" is arriving in terms of my memory requirements and some sloppy code I've used that now wants to be able to write to ROM. lol. So a few questions on the best way to organize things on a cart. Keep in mind my goal is to run off a multi-bank cart on a stock 16K console. From a quick and dirty analysis, my storage requirements appear to be approx: Compiled code: 5K (will increase) Char patterns / sprites: 5K (will increase) Maps: 9K now, going to ??? As I understand it, I can use as many 8K banks of ROM as required for my cartridge, and dynamically switch between them each time I need to access something from one or the other. EDIT>> I just noticed this: Quote - cartridges that can be plugged directly into the console can provide upto 40K of GROM and upto 16K of ROM, Is that a real restriction nowadays? My question is, how many banks can I have accessible at one time? I am assuming 2? So one for executing code, and another for whatever resources you are needing to load (char patterns, or maps, in my case)? Would it make sense to have one bank for code, one for char / sprite patterns, and multiple for maps as required? This would require dynamically swapping the 2nd char pattern / map banks, but possibly only when the player travels to a new map screen (so not every frame). Is there a performance penalty for switching banks? Does this mean I should really try to keep my main loop code under 8K so it fits on a single bank? Any resources on this stuff somewhere I can review? Thanks in advance! Edited February 28, 2023 by retrodroid 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 28, 2023 Share Posted February 28, 2023 27 minutes ago, retrodroid said: My question is, how many banks can I have accessible at one time? I am assuming 2? So one for executing code, and another for whatever resources you are needing to load (char patterns, or maps, in my case)? Unfortunately only one 8K bank in the >6000->7FFF region at a time. So it's much easier if you run the code from 32K RAM. If you don't want 32K as a requirement you could perhaps load graphics from GROM? Otherwise you need to have banks with both code and graphics. 29 minutes ago, retrodroid said: Would it make sense to have one bank for code, one for char / sprite patterns, and multiple for maps as required? This would require dynamically swapping the 2nd char pattern / map banks, but possibly only when the player travels to a new map screen (so not every frame). Sure. 30 minutes ago, retrodroid said: Is there a performance penalty for switching banks? Does this mean I should really try to keep my main loop code under 8K so it fits on a single bank? It doesn't take longer than the instruction to switch the bank. 1 Quote Link to comment Share on other sites More sharing options...
retrodroid Posted February 28, 2023 Share Posted February 28, 2023 20 minutes ago, Asmusr said: Unfortunately only one 8K bank in the >6000->7FFF region at a time. So it's much easier if you run the code from 32K RAM. If you don't want 32K as a requirement you could perhaps load graphics from GROM? Otherwise you need to have banks with both code and graphics. Sure. It doesn't take longer than the instruction to switch the bank. Well that does complicate things. I have a burning desire to not require 32KB expansion, probably some latent negative feelings towards it from when I was a kid and didn't have it then. I have nothing against GROM, however, just not sure how to configure my code to use it. The char patterns and map data could all live happily in GROMs. I'm fairly confident my game code can fit in a single 8K ROM. Suggestions on where to find a tutorial or reference for configuring GROMs? I'm using Classic99 for development, btw. 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.