+Lee Stewart Posted December 28, 2019 Share Posted December 28, 2019 9 hours ago, Airshack said: I was using Asm994a which didn't seem to flag it or provide warning. As indicated by @FarmerPotato, the assembler (both Assm994a and E/A), upon getting the ‘R’ flag adds to your code R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 The ‘Rn’ EQUates are strictly mnemonics for our eyes. The two mentioned assemblers do not care—R0 – R15 are just numbers and assemble without error where numbers are expected as you noted. ...lee 1 Quote Link to comment Share on other sites More sharing options...
BillG Posted December 29, 2019 Share Posted December 29, 2019 How much existing code uses just the register number instead of Rx? Is it worth a mode in which the assembler requires the Rx form? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 29, 2019 Share Posted December 29, 2019 16 minutes ago, BillG said: How much existing code uses just the register number instead of Rx? A lot: Most (all?) of the disassembled code on Thierry’s site. The disassembled code in Heiner Martin’s TI Intern. The original assembly listing of TI Forth, which also used a significant amount of non-Rn EQUates. For example, the TI Forth workspace was dubbed TEMP0 – TEMP7, UP, SP, W, LINK, CRU, IP, RP, NEXT, corresponding to R0 – R15, respectively). The original source code for the TI-99/4A ROM 0 (I think) . . . and a lot more. 16 minutes ago, BillG said: Is it worth a mode in which the assembler requires the Rx form? I think @FarmerPotato’s suggestion of a warning when the Rn EQUates (and, possibly, any EQUates) are used for immediate operands would be preferable, though it might create more trouble than it is worth. ...lee 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted December 30, 2019 Share Posted December 30, 2019 I see now.... C R8,R9 * the assembler is looking for registers so this is the same as... C 8,9 * I personally dislike referencing registers here without the ‘R’ simply for beginner readability * so I always use the ‘R’ as a form of better documenting my code CI R8,R9 * since the assembler is looking for a register and an immediate, it sees CI R8,9 I doubt any coder would ever intentionally wish to place an ‘R’ in front of an immediate constant in this way. This ‘typo’ of mine took a while to figure out because as an assembly beginner it was difficult to see without a warning. Thanks for the clarification guys. 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted December 30, 2019 Share Posted December 30, 2019 Next Question: How do you guys manage an assembly program’s size? Since I don’t fully understand how the assembler parcels out memory, other than with the specific in-code declarations I assign. BASIC has warnings for low memory and a command to let you know how much memory is available. What’s the quick and dirty for for doing this with an assembly program under say EA3 option? My current project produces an object code file which Ti99Dir says is of Size 251; disk size I’m using is 720 sectors, used is 254 sectors; free is 466. Any tricks in Classic99 I can use to check program size or mem available once loaded? Any pitfalls to avoid or or think about as program size inflates? Quote Link to comment Share on other sites More sharing options...
PeteE Posted December 30, 2019 Share Posted December 30, 2019 (edited) This is a warning with Ralph's latest xas99: > bnp.asm <2> 1317 - Warning: Register R9 used as immediate operand IntelliJ IDEA editor will even show the little red squiggle when using the wrong operand type: Edited December 30, 2019 by PeteE 2 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted December 30, 2019 Share Posted December 30, 2019 45 minutes ago, PeteE said: This is a warning with Ralph's latest xas99: > bnp.asm <2> 1317 - Warning: Register R9 used as immediate operand IntelliJ IDEA editor will even show the little red squiggle when using the wrong operand type: Thanks PeteE. Upon your recommendation I’m using the IntelliJ IDEA 2017.1.5 editor with xtd99 IntelliJ Plugin, which provides these red squiggles yet I’ve somehow toggled this error correction option off? It no longer provides these visual queues. Maybe an update turned that off? Damn....now I have to get that working again. I’m using plugin version 1.5.1 updated for IDEA 15. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted December 30, 2019 Share Posted December 30, 2019 2 hours ago, Airshack said: Next Question: How do you guys manage an assembly program’s size? Since I don’t fully understand how the assembler parcels out memory, other than with the specific in-code declarations I assign. BASIC has warnings for low memory and a command to let you know how much memory is available. If you actually get into trouble with memory limitations for your machine code, you have a really big project. The worse problem is buffer space for your data, and this is something you can handle more easily. In many cases you'd take some explicitly defined memory area (e.g. from E000-FFFF). For all my assembly language projects, I never had any concerns about memory space. Remember that machine language is very efficient in space. For instance, assume that your average assembly code line has 4 bytes (lots of them with 2, others with 6, many with 4), a machine program with 8 KiB size (program image) means 2048 lines of code in average, and if you print your source code in two columns with 50 lines, you'll fill more than 20 pages. 1 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted December 31, 2019 Share Posted December 31, 2019 5 hours ago, Airshack said: Any tricks in Classic99 I can use to check program size or mem available once loaded? In Classic99, load your program, bring up the debugger or press scroll lock then press F10 ...accept dialog... Goto Classic99's root folder and open MEMDUMP.BIN with a hex-editor, find and highlight your program, the size should be indicated somewhere on the status bar. That's what I do. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted December 31, 2019 Share Posted December 31, 2019 On 10/31/2019 at 5:47 PM, intvnut said: You might be slightly faster if you always CLR TOS, and then conditionally SETO, to avoid the extra unconditional JMP. CLR doesn't modify the flags. Something like this (guessing at the syntax): \ cx ax bx \ R1 R0 tos CODE WITHIN ( n lo hi -- flag ) R0 POP, R1 POP, R0 TOS SUB, R0 R1 SUB, TOS R1 SUB, TOS CLR, NC IF, TOS SETO, ENDIF, NEXT, ENDCODE A while back Intvnut gave me this code. (in perfect Forth Assembler I might add) While it worked perfectly it was 6 bytes bigger than the equivalent Forth version although of course faster. I was not sure that this would work but I gave it a try. By removing the POP macros, which are just *SP+ <Rx> MOV, and referencing the stack with indirect addressing I remove 4 byes and so it is worth using it to replace the Forth version in my tiny 8K kernel space. By way of explanation: 1. TOS is just an alias for R4 and is a "cache" for the tos of stack. (makes the VM look like an accumulator machine) 2. This means the 1st parameter "hi" is in R4 on entry. 3. "lo" is the 1st item on the stack in memory 4. "n" parameter is the 2nd item on the stack in memory. CODE: WITHIN ( n lo hi -- flag ) *SP TOS SUB, *SP+ *SP SUB, TOS *SP+ SUB, TOS CLR, NC IF, TOS SETO, ENDIF, NEXT, END-CODE \ 2 bytes bigger than Forth 2 Quote Link to comment Share on other sites More sharing options...
intvnut Posted December 31, 2019 Share Posted December 31, 2019 1 hour ago, TheBF said: A while back Intvnut gave me this code. (in perfect Forth Assembler I might add) Whoo hoo! I eyeballed it correctly. 1 hour ago, TheBF said: CODE: WITHIN ( n lo hi -- flag ) *SP TOS SUB, *SP+ *SP SUB, TOS *SP+ SUB, TOS CLR, NC IF, TOS SETO, ENDIF, NEXT, END-CODE \ 2 bytes bigger than Forth Very nice. It seemed like the POP macros were unneeded overhead. They make the code easier to follow, but direct SP manipulation seems more efficient (space, and hopefully time). 2 Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 31, 2019 Share Posted December 31, 2019 12 hours ago, Airshack said: Next Question: How do you guys manage an assembly program’s size? Since I don’t fully understand how the assembler parcels out memory, other than with the specific in-code declarations I assign. BASIC has warnings for low memory and a command to let you know how much memory is available. If you want to be sure, generate a listing file (L with E/A, though you need to write it somewhere. With Classic99 I'd write it as a Windows file with the ?W tag for easier reading. ) The listing will give you a good idea how big the program is - just scroll down. If the addresses are relative, then you'll see how many bytes are used. If they are absolute, you'll see the actual last address used. You'll also get a symbol list showing where all your named labels are. 3 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 1, 2020 Share Posted January 1, 2020 16 hours ago, Tursi said: If you want to be sure, generate a listing file (L with E/A, though you need to write it somewhere. With Classic99 I'd write it as a Windows file with the ?W tag for easier reading. ) The listing will give you a good idea how big the program is - just scroll down. If the addresses are relative, then you'll see how many bytes are used. If they are absolute, you'll see the actual last address used. You'll also get a symbol list showing where all your named labels are. That’ll come in handy — thank you! I’m probably under-utilizing the debug tools with Classic99. I’ve figured out how to watch specific VDP and CPU memory locations, monitor the Register space, and watch the status bits, program counter and other obvious stuff, which is extremely useful — fun. Setting breakpoints in Classic99 is something I’d like to use. It’s not so obvious. Maybe I need to examine the readme.txt or something? Quote Link to comment Share on other sites More sharing options...
Tursi Posted January 2, 2020 Share Posted January 2, 2020 23 hours ago, Airshack said: That’ll come in handy — thank you! I’m probably under-utilizing the debug tools with Classic99. I’ve figured out how to watch specific VDP and CPU memory locations, monitor the Register space, and watch the status bits, program counter and other obvious stuff, which is extremely useful — fun. Setting breakpoints in Classic99 is something I’d like to use. It’s not so obvious. Maybe I need to examine the readme.txt or something? Click the question mark under the breakpoint box, and it will give you a summary of the syntax for each breakpoint type. But yes, reading the manual (help->classic99 manual, or the pdf in the install folder) helps. 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 2, 2020 Share Posted January 2, 2020 11 hours ago, Tursi said: Click the question mark under the breakpoint box, and it will give you a summary of the syntax for each breakpoint type. But yes, reading the manual (help->classic99 manual, or the pdf in the install folder) helps. I’ll click on that question mark to see if I can figure it out before resorting to RTFM. :) Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 23, 2020 Share Posted January 23, 2020 I have a game development situation: In order to avoid using more than four sprites in the same horizontal row, I’ve decided to “drop” a key onto my game map using a background tile vs using a fifth sprite. The game is a vertical scroller with the play area roughly the size of four TI screens vertically. At the beginning of my code I load a Magellan assembly data formatted map into memory. The assembler takes care of where... I have a pointer to this map data memory location called MAPDAT. It turns out the assembler mysteriously assigns the map location (top left tile location) to: >C5B0. In Upper Expansion RAM. @MAPDAT = >C5B0 (50,608) >C5B0 holds character >8B I’ve used the debugger in Classic99 to verify my map data is in fact loading properly at this location. My scroller is working... Question: Is it possible to overwrite the data located at >C5B0? I’ve previously only used VDP console RAM read/writes. I guess I need a kickstart on accessing upper expansion RAM. There’s something simple I’m overlooking perhaps? Obviously the data at >C5B0 and beyond is part of my code listing. It’s not logic — just data. Would modifying this data be considered self-modification of code? It’s possible I’m over-complicating something easy here. Just late and my progress has halted. Help! 1 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted January 23, 2020 Share Posted January 23, 2020 8 minutes ago, Airshack said: I have a pointer to this map data memory location called MAPDAT. It turns out the assembler mysteriously assigns the map location (top left tile location) to: >C5B0. Question: Is it possible to overwrite the data located at >C5B0? I’ve previously only used VDP console RAM read/writes. Obviously the data at >C5B0 and beyond is part of my code listing. It’s not logic — just data. Would modifying this data be considered self-modification of code? Obviously you can read from the MAPDAT and move data to the VDP. >C5B0 is CPU RAM. Your program can read and write to MAPDAT (since it's RAM). So yes, you can overwrite the data. It's probably not uncommon to overwrite data (once loaded). No, it's not self-modifying code. You're modifying data, not code. It's probably uncommon to modify code. 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 23, 2020 Share Posted January 23, 2020 1 hour ago, sometimes99er said: So yes, you can overwrite the data. It's probably not uncommon to overwrite data (once loaded) So I may then use a simple register-to-memory or memory-to-memory application of MOVB to get the job done? Seems so much easier than working with the VDP RAM via ports. I don’t know why it’s not working out for me. Zero examples in the EA manual of mem-to-mem and reg-to-mem, and probably failing due to fatigue...zzz. Will try in the AM. LI R0, >D900 MOVB RO,@MAPDAT * to replace byte at MAPDAT w >D9 I think I tried this earlier and received a warning. Will the 8bit data path to upper expansion ram result in MOV operating transparently even though it moves 16bits? 2 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted January 23, 2020 Share Posted January 23, 2020 1 hour ago, Airshack said: LI R0, >D900 MOVB RO,@MAPDAT * to replace byte at MAPDAT w >D9 Probably just a typo in your post, but in the second line you use an O instead of a 0 in R0. 2 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted January 23, 2020 Share Posted January 23, 2020 1 hour ago, Airshack said: So I may then use a simple register-to-memory or memory-to-memory application of MOVB to get the job done? Yep. 1 hour ago, Airshack said: Seems so much easier than working with the VDP RAM via ports. Yep. I usually restrain myself to unexpanded console, and then sometimes have to use VDP RAM instead of CPU RAM (ScratchPad is always there). You wrap it up (in code) so there's actually not much to it. Of course one has to do a lot of MOVB to the VDP to get a game going. 1 hour ago, Airshack said: Will the 8bit data path to upper expansion ram result in MOV operating transparently even though it moves 16bits? Yep. Overall a MOV is faster than 2 MOVB's, but ... MOVB has "the byte address flexibility" (if you're hitting memory with that size (wanting 8-bits rather than 16) ). Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 23, 2020 Share Posted January 23, 2020 What a difference some coaching, some sleep, and a cup of coffee make! Of course my problem was undetectable near bedtime. Thanks @sometimes99er & @Asmusr. It’s almost thrilling to simply manipulate expanded RAM without messing around with the VDP portal routines. So this must be what it’s like to develop on a system with no VDP between the CPU and RAM. Of course the other retro systems of the era are hampered by: 8-bit registers, fewer registers, less capable registers, no divide and multiply op codes, etc. I suppose the VDP memory access restrictions aren’t that big of a deal considering the power of the 9900, vs Z80 or 6502. Anyway, it’s working now. I have a bridge key on my game map! MOV @MAPDAT, R6 * pointer to beginning of map LI R7,>D900 * Character D9 = bridge key MOVB R7,*R6 * Place key at map origin as a test My problem last night was I was using the following first line: LI R6, @MAPDAT * then basically corrupting MAPDAT Caused all sorts of havoc onto my game screen. 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 23, 2020 Share Posted January 23, 2020 5 hours ago, sometimes99er said: I usually restrain myself to unexpanded console, and then sometimes have to use VDP RAM instead of CPU RAM (ScratchPad is always there). At this point in my learning cycle I exercise little control over where the assembler is going to locate my code. Big Picture Wise: How may I restrict myself to the unexpanded console RAM? Quote Link to comment Share on other sites More sharing options...
PeteE Posted January 23, 2020 Share Posted January 23, 2020 3 minutes ago, Airshack said: At this point in my learning cycle I exercise little control over where the assembler is going to locate my code. Big Picture Wise: How may I restrict myself to the unexpanded console RAM? The assembler should give you total control of where you put your code. I'm assuming you have something like this in your assembly program: AORG >A000 ; start at upper expansion RAM * your program code MAPDAT BYTE .... ; your map data from Magellan BYTE .... In order to run on an unexpanded console, you need to put your program in cartridge ROM like this: AORG >6000 ; start at cartridge ROM * cartridge header * your program code MAPDAT BYTE .... ; your map data from Magellan BYTE .... ; note this is now read-only Note that you can no longer modify the MAPDAT table at its assembler-defined address in ROM, but you must copy it to the VDP to be displayed and then you can modify it in VDP RAM through the VDP port. To use the scratchpad for data, I use a group of EQUates to define address of variables, leaving room for the register workspace, and calculate the offsets manually by adding the size of the previous item to the current offset: WRKSP EQU >8300 ; workspace at top of scratchpad PLAYER EQU WRKSP+32 ; 32 is the size of WRKSP, player is 2 bytes ENEMY EQU WRKSP+34 ; 2 bytes after PLAYER, enemy is 2 bytes KEYLOC EQU WRKSP+36 ; 2 bytes after ENEMY, keyloc is 2 bytes ETC Keep in mind the scratchpad is only 256 bytes, so the offset cannot exceed 255... and you either need to avoid using scratchpad data used by the ISR, or keep interrupts off (LIMI 0) for the duration of your program. 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted January 23, 2020 Share Posted January 23, 2020 48 minutes ago, PeteE said: The assembler should give you total control of where you put your code. I'm assuming you have something like this in your assembly program: AORG >A000 ; start at upper expansion RAM * your program code MAPDAT BYTE .... ; your map data from Magellan BYTE .... Actually, No! I’m not using AORG at all. There’s no absolute addressing of my program code. While studying the EA manual I incorrectly assumed that an omission of AORG would simplify matters. What I believe I am realizing now is I’ve simply chosen to defer control over where my code is stored. I was vaguely familiar with the assembler directive AORG from messing around with the mini-memory cartridge. Seems my game project began and has grown wildly without using AORG to manage absolute addressing. This being my first assembly game and all, I was pretty happy to let the assembler do its thing. It appears AORG is going to be necessary if I want this game to ever run from a cartridge. Correct? Also, I’ll need to find another way to place keys upon my game background as ROM map images are obviously impossible to manipulate in the manner I’ve recently implemented. One thought: If I keep track of where my key objects should be located on the scrollable game map, I can simply plot them over grass tiles, after each viewport redraw. I’m imagining this will create a blinking appearance as the map is continually redrawn, and the key is then replotted. Perhaps it will appear as a nice feature highlighting the key’s location? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 23, 2020 Share Posted January 23, 2020 7 minutes ago, Airshack said: It appears AORG is going to be necessary if I want this game to ever run from a cartridge. Correct? Pretty much. ...lee 1 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.