sometimes99er Posted March 2, 2019 Share Posted March 2, 2019 (edited) D'oh. Edited March 2, 2019 by sometimes99er Quote Link to comment Share on other sites More sharing options...
matthew180 Posted March 2, 2019 Author Share Posted March 2, 2019 I asked Karl Guttag about what happens if you read the status register at the same moment when the flag is being sent in the 9918A. He said he did not know specifically about that condition, but he was pretty sure that the 9918A did not guard against those kinds of hazards. I suspect the code with the consecutive conditional jumps is polling fast enough to expose the hazard of setting and clearing the frame-flag at the same time. Actually, the MOVB loop is also capable of exposing the hazard, but probably not as often as the conditional jump loop. The F18A used to specifically guard against this hazard, but in trying to be 100% compatible with the 9918A, the F18A now models the hazard, i.e. if you read the status register at the same time the frame-flag is being set, the flag will be cleared and reported as clear. Basically, polling the VDP directly risks dropping frames. IMO, the best method is to use the interrupt associated with the VDP and use the ISR to just set a flag to true. Your polling loop checks your flag, and when it is true, exit the loop, clear the flag, and continue as usual. Or on the 99/4A, poll the 9901 as mentioned earlier. You could also use a counter in your ISR instead of a true/false flag, which allows you to know if you missed frames. The ISR increments the counter, and your polling loop checks for a value greater-than zero; and if true, exit the loop, *copy the ISR count*, reset ISR count to 0. Now you have the number of frames since your last loop, and if greater than 1 you can decide what to do about it (if anything). Then, as far as I remember, it also fails on the F18A where the 5th sprite bits can be zero. In the V1.6 (in 2014) firmware I made a compatibility change for reporting 5th sprite values. I decoupled the status register n-th sprite reporting from the actual number of sprites displayed. The original problem was due to the F18A's ability to show all 32 sprites on a line, the 5th-sprite flag was always clear (as well as the sprite-number bits). The change I made was to report the 5th sprite, regardless of how many sprites are being displayed, when the F18A is locked. When unlocked, the flag is set when the sprite_max value (VR30) is reached, which never happens if VR30 is 31 (i.e. max-sprites is all 32 sprites). I also changed the sprite-bits in the status register to follow the current sprite being processed during a scan line as long as the 5th-sprite flag is clear. This appears to be the behavior of the 9918A. Once the 5th sprite is detected, the 5th-sprite flag is set and sprite processing stops, which provides the 5th-sprite value number to the status register. The F18A models this behavior. 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 3, 2019 Share Posted March 3, 2019 (edited) I suspect the code with the consecutive conditional jumps is polling fast enough to expose the hazard of setting and clearing the frame-flag at the same time. Actually, the MOVB loop is also capable of exposing the hazard, but probably not as often as the conditional jump loop. I specifically tested for it years ago and was able to prove it can happen.. I'd expect the same thing. On the TI we don't need to enable the ISR if you don't mind polling. Since the VDP interrupt is wired through the CRU, you can just test CRU bit 2 to see if the line is high. Setting a flag in a user ISR is also good - I tend to do the latter on the ColecoVision where the ISR is an NMI. (edit: all of which Matt already said.. never mind. ) Edited March 3, 2019 by Tursi Quote Link to comment Share on other sites More sharing options...
Airshack Posted March 3, 2019 Share Posted March 3, 2019 Since the VDP interrupt is wired through the CRU, you can just test CRU bit 2 to see if the line is high. Safe to say there’s a consensus here regarding CRU bit 2 testing vs polling VDP Status Register for previously stated reasons? Added bonus is no interrupts enabled so scratchpad RAM isn’t “trampled upon.” Sent from my iPhone using Tapatalk Pro 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted March 3, 2019 Share Posted March 3, 2019 Safe to say there’s a consensus here regarding CRU bit 2 testing vs polling VDP Status Register for previously stated reasons? Yes. Still, the only problem is that it doesn't work on the Dijit AVPC card. Does anyone have a list of the scratchpad addresses you cannot use if you use the ISR? Quote Link to comment Share on other sites More sharing options...
hhos Posted March 3, 2019 Share Posted March 3, 2019 Does anyone have a list of the scratchpad addresses you cannot use if you use the ISR? There is a listing in the E/A manual on pages 404-406. The description of the ISR, DSR, etc. usage of this memory, as described on these pages, has such a large foot print that I have thrown out any idea of allowing the current interrupt system any access. I don't know of any other list, and I've seen this one referenced every time I've seen the subject come up, as far as I can recall anyway. HH Quote Link to comment Share on other sites More sharing options...
matthew180 Posted March 3, 2019 Author Share Posted March 3, 2019 I did read through the TI-Intern ISR disassembly at some point long ago, but I don't think I made any notes about scratch pad memory use. :-( Posts #38 and #40 (back on pg. 2 of this thread) explain a little about the ISR and what parts of it can be disabled. Then there is my post 2-years later where I reluctantly embrace the ISR: #232, pg 10: http://atariage.com/forums/topic/162941-assembly-on-the-994a/page-10?do=findComment&comment=2797433 That gives a code example of how to use the the ISR is the most minimal form, which I probably tested (I usually don't post code without testing it... usually...). With most of the ISR services disabled, there is probably not a lot of scratch pad that you need to avoid. Of course there is the ISR hook address, and I think one workspace close to the end of scratch pad. Of course this assumes you are not planning on calling any GPL or ROM routines, and you can be sure no other devices have triggered an interrupt (that would allow a DSR to run, for example). 1 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted March 3, 2019 Author Share Posted March 3, 2019 (edited) So I just did a review of the ISR again, only paying attention to the code flow when the interrupt is caused by the VDP, and the VDP "allowed services" are all disabled. Here is the summary: ISR Vector WP >83C0 ISR in ROM at: >0900 First thing: LIMI 0 LWPI >83E0 <--- Change workspace to GPL Test if interrupt was cassette: No. Test if interrupt was for VDP: Yes (in this case), jump to >094A >094A, VDP interrupt: MOVB @>83C2,R1 Shift R1 left 1-bit, see if *any* VDP services are allowed If set, branch to >0A84, no services allowed Otherwise, check each service: >0958: Shift R1 left, JOC >09E8 (no sprite processing allowed) >09E8: Shift R1 left, JOC >0A66 (no sound processing allowed) >0A66: Shift R1 left, JOC >0A84 (no QUIT allowed) >0A84: Read VDP status byte into >837B ** R15 in GPLWS contains VDP address vector >8C02 LWPI >83C0, initial ISR vector workspace INC R11, which is address >83D6, if zero blank screen LWPI >83E0, back to GPLWS Updates >8379, screen timeout counter value Check ISR Hook >83C4, if not zero, BL @>83C4 LWPI >83C0, back to ISR vector workspace RTWP, end the ISR Notable addresses used: >8379, copy of screen timout value >83C2, accessed directly, VDP ISR allowed services >83D4, accessed via R10 with WP set to >83C0, current VDP VR1 value >83D6, accessed via R11 with WP set to >83C0, screen blank timeout >83FE, accessed via R14 with WP set to >83E0, VDP access address >8C02 Observations: * The workspace is ping-ponged back and forth between the GLPWS and the ISRWS. This means the scratch pad from >83C0 .. >83FF is pretty much off limits. * There are assumed values in some of the GPLWS, notably R15 which contains >8C02 (the VDP write address), and that register is used as a base value to calculate the other VDP addresses (like when reading the VDP status register). * The ROM commonly accesses specific memory through registers, similar to how my VDP routines send the MSB of R1 by knowing it will be at a specific memory address. * There seems to be no consistency in the ROM for accessing specific memory directly, i.e. as an address like >83C0, or via mapped registers. It really makes it a pain in the ass to follow sometimes. * The ISR does not seem to issue a LIMI 2 when it is done. The interrupt mask is stored in the calling workspace, which is restored when the ISR returns with RTWP. * Don't let >83D6 even be zero to avoid having the ISR blank the VDP. * Keep a copy of your VR1 in >83D4. So, basically to use the ISR without any of the services: * Don't use >83C0 .. >83FF in scratch pad * Know that >8379 will be overwritten every time the ISR is called (contains a copy of the timeout value) * Set your hook-routine address in >83C4, load your own workspace, restore the GLPWS before return, and return from your routine with B *R11. * Disable the ISR services by writing >FF to >83C2 * Write >FF to >83D6 Edit: write >0001 to address >83D6 every time through your game loop to avoid screen blank * Put a copy of your VDP VR1 into >83D4 I think that is about it. Let me know how it goes. Edit: See above. I forgot the ISR *increments* the 16-bit value at >83D6. Actually, it increments by 2 (INCT), and if the key routine that resets it to >0000 could be avoided, then you could set the value to >0001 once and never have to worry about it again (since the value will never actually be >0000). Edited March 3, 2019 by matthew180 2 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted March 3, 2019 Share Posted March 3, 2019 (edited) Edit: Sorry Matthew, I didn't see your last post before I did this myself. Looking at the disassembly in TI Intern, the ISR with as much a possible turned off seems to be using at least these addresses: GPL WS (>83E0) R1,R8,R12,R14,R15 INT WS (>83C0) R13-15 >83C2 ISR flags >83C4 ISR address >837B VDP status >83D6-7 Screen timeout counter >8379 VDP interrupt timer Actually it would probably be best not to use any address above >83C0. This means I cannot use the ISR for my latest project. Edited March 4, 2019 by Asmusr 2 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted March 3, 2019 Author Share Posted March 3, 2019 Two reviews is better than one. :-) I guess I would fall back to checking the CRU directly then, like the ISR is doing. I don't know what the "Dijit AVPC card" is, but it has to trigger the ISR somehow, no? If supporting that card is important, then maybe detect the card and use an alternative method for the ISR in that case? 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted March 3, 2019 Share Posted March 3, 2019 I'm really happy that I installed 16-bit wide RAM in my console. Thus any memory I use is equally fast. 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted March 3, 2019 Share Posted March 3, 2019 Edit: Actually it would probably be best not to use any address above >83C0. This means a cannot use the ISR for my latest project. Cost: CPU RAM PAD is located at addresses >8300 through >83FF. 256 measly BYTES! ISR uses the high memory locations at addresses >83CO through >83FF. 64 BYTES! (25% hit) Conclusion: LIMI 0 Sent from my iPhone using Tapatalk Pro 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted March 3, 2019 Share Posted March 3, 2019 I'm really happy that I installed 16-bit wide RAM in my console. Thus any memory I use is equally fast. Too bad TI never did otherwise we could all develop with that in mind. Sent from my iPhone using Tapatalk Pro Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 3, 2019 Share Posted March 3, 2019 Thierry Nouspikel’s website also has good information on scratchpad RAM use. ...lee 1 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted March 5, 2019 Author Share Posted March 5, 2019 +1 for Thierry's website, it is a great resource. He covers the interrupts in detail, and it was because I reviewed his site that I found edits in my own post. 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 7, 2019 Share Posted March 7, 2019 A game like TI Scramble runs the entire main loop between two vsyncs, so you have more time than you may think. You have 50000 clock cycles in NTSC between two vsyncs, and you can use Classic99 to measure how much time you have used: Add a breakpoint with the start and end addresses of you main loop, e.g. T(A024-A038). Updates to the display you should try to finish as soon as possible after vsync. If you use two name tables as a double buffer you can update alternating tables each frame and just do a page flip right after vsync. I have even double buffered the sprite attribute table this way. Timing of sound playing is less important, I often do it after all the other work has been done. If you run over the frame, perhaps deliberately, remember to read the VDP status register once to clear the interrupt before you wait for the next one. Otherwise your polling loop will terminate immediately in the middle of a frame. You must also read the VDP status after detecting the interrupt, like this: vsync: movb @vdpsta,r12 clr r12 vsync_1: tb 2 ; Test CRU bit for VDP interrupt jeq vsync_1 movb @vdpsta,r12 rt In Flying Shark the main loop takes up to 4 frames depending of the complexity of the graphics. In that game I had to count the frames and add delays in order to obtain an even pace, which was a real pain. If possible try to do approximately the same amount of work each frame. That doesn't mean you have to do the same things each frame. One frame can move the sprites while another scrolls the screen, for instance. I am using your vsync loop with success. My game loop is: LOOP LIMI 0 wait for vsync draw 500 bytes to VDP for scrolling bitmap playing field and sprites increment counters test counters to see if sprites should go to next animation update playing field in CPU RAM tell music players to go 1 tick KSCAN The music is playing at regular speed and my tick counter is advancing at 60 Hz so all's well. I'm not giving the ISR any time. 2 Quote Link to comment Share on other sites More sharing options...
Airshack Posted March 7, 2019 Share Posted March 7, 2019 I am using your vsync loop with success. My game loop is: LOOP LIMI 0 wait for vsync draw 500 bytes to VDP for scrolling bitmap playing field and sprites increment counters test counters to see if sprites should go to next animation update playing field in CPU RAM tell music players to go 1 tick KSCAN The music is playing at regular speed A. I’d like to see how your music player(s) work. B. KSCAN? Won’t that mess with the Scratchpad too? Sent from my iPhone using Tapatalk Pro Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 7, 2019 Share Posted March 7, 2019 A. I’d like to see how your music player(s) work. B. KSCAN? Won’t that mess with the Scratchpad too? Right.. KSCAN. I'm not using PAD aggressively, just my WS in >8300. I must re-read this discussion if I want to take over more of PAD (like, storing my VDP write loop code). The music player is based on FORTI in pure assembly (not FORTH this time). I'll be posting all the source here shortly. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted March 7, 2019 Share Posted March 7, 2019 KSCAN is not only messing with scratchpad but it's also quite slow because it's doing far more than you usually need to check a key in a game. Here is a routine I use to check a key. Just load r0 with one of the equates, e.g. li r0,KEY_A and bl @check_key. On return jeq moves you on if the key was not pressed. In specific cases where you need to check multiple keys, e.g. the joystick, you can do faster by reading multiple CRU bits, but my routine is still a lot faster than KSCAN. ********************************************************************* * * Check key * * r0: Column in MSB: >0000 - >0700, Row in LSB: >0006 - >0014 * * Column 0 1 2 3 4 5 6 7 * Row * >0006 = . , M N / Fire Fire * >0008 Space L K J H ; Left Left * >000A Enter O I U Y P Right Right * >000C 9 8 7 6 0 Down Down * >000E Fctn 2 3 4 5 1 Up Up * >0010 Shift S D F G A * >0012 Ctrl W E R T Q * >0014 X C V B Z * * On return NEQ means that the key is pressed * KEY_FI EQU >0606 KEY_LF EQU >0608 KEY_RG EQU >060A KEY_DN EQU >060C KEY_UP EQU >060E KEY_CM EQU >0206 KEY_FS EQU >0106 KEY_0 EQU >050C KEY_1 EQU >050E KEY_2 EQU >010E KEY_3 EQU >020E KEY_4 EQU >030E KEY_5 EQU >040E KEY_6 EQU >040C KEY_7 EQU >030C KEY_8 EQU >020C KEY_9 EQU >010C KEY_A EQU >0510 KEY_B EQU >0414 KEY_C EQU >0214 KEY_D EQU >0210 KEY_E EQU >0212 KEY_F EQU >0310 KEY_G EQU >0410 KEY_H EQU >0408 KEY_I EQU >020A KEY_J EQU >0308 KEY_K EQU >0208 KEY_L EQU >0108 KEY_M EQU >0306 KEY_N EQU >0406 KEY_O EQU >010A KEY_P EQU >050A KEY_Q EQU >0512 KEY_R EQU >0312 KEY_S EQU >0110 KEY_T EQU >0412 KEY_U EQU >030A KEY_V EQU >0314 KEY_W EQU >0112 KEY_X EQU >0114 KEY_Y EQU >040A KEY_Z EQU >0514 KEY_SP EQU >0008 KEY_EN EQU >000A KEY_FN EQU >000E KEY_SH EQU >0010 KEY_CT EQU >0012 JOY_FI EQU >0606 JOY_LT EQU >0608 JOY_RT EQU >060A JOY_DN EQU >060C JOY_UP EQU >060E * check_key: li r12,>0024 ; CRU address of the column decoder ldcr r0,3 ; Select column andi r0,>00ff mov r0,r12 ; Select row tb 0 ; Test key, EQ if not pressed rt *// check_key 3 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted March 7, 2019 Author Share Posted March 7, 2019 KSCAN is not only messing with scratchpad but it's also quite slow because it's doing far more than you usually need to check a key in a game. ... Like pausing for 8mS, twice, to debounce in code. @FarmerPotato, there has been a lot of keyboard and KSCAN discussion around pg. 10 in this thread. My post that dissects the delay in KSCAN is here: http://atariage.com/forums/topic/162941-assembly-on-the-994a/page-10?do=findComment&comment=2840302 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 7, 2019 Share Posted March 7, 2019 Like pausing for 8mS, twice, to debounce in code. @FarmerPotato, there has been a lot of keyboard and KSCAN discussion around pg. 10 in this thread. My post that dissects the delay in KSCAN is here: http://atariage.com/forums/topic/162941-assembly-on-the-994a/page-10?do=findComment&comment=2840302 OK, KSCAN will be toast. I will check for movement keys/fire, maybe Redo/Back. The column setup can be combined. Thanks Rasmus! KEY_FN EQU >000E KEY_FS EQU >0106 KEY_9 EQU >010C KEY_S EQU >0110 KEY_X EQU >0114 KEY_D EQU >0210 KEY_8 EQU >020C KEY_E EQU >0212 KEY_Q EQU >0512 JOY_FI EQU >0606 JOY_LT EQU >0608 JOY_RT EQU >060A JOY_DN EQU >060C JOY_UP EQU >060E 1 Quote Link to comment Share on other sites More sharing options...
Airshack Posted March 8, 2019 Share Posted March 8, 2019 On a related yet much less technical note... I’ve always felt the early computer games overused the keyboard. Lots of really poor UI out there... Examples: “Press J for joystick or K for keyboard” or “Press Enter/Return to start game.” or “Press 1 to play, 2 to exit.” or “Press Spacebar to begin” or “Make sure alpha-lock is....” or As a gamer I much prefer joystick based menus with button presses or Joystick movement to select options. Ex: Building in a joystick-up menu movement requirement prior to starting your game assures Alpha-Lock is released on the TI console, well before gameplay begins, every time. It’s understood the TI console did not come with a joystick. Is it not safe to assume each potential player has one by now? Why punish all players with zero value added keyboard driven UIs? Text adventures may be the exception here. They may also be the reason bad UIs became the standard prior to action games: sports, shooters, etc. Nothing worse than having to get up off the couch to restart a game. Seriously, I didn’t buy a joystick cable extender so I can now get up and press the 1 key to restart each and every game. Friends don’t let friends KSCAN. Sent from my iPhone using Tapatalk Pro 1 Quote Link to comment Share on other sites More sharing options...
Casey Posted March 8, 2019 Share Posted March 8, 2019 But you have to consider the times the 99/4A was released in. Most people didn't have computer exposure prior to getting one, and if you just said "Use Joystick to make selection" and you couldn't move up because the Alpha Lock key was engaged, and didn't provide a reminder message, the novice user would likely be pretty frustrated with your program very quickly. I know there was an addendum thing in the pile of docs that came with the 99/4A that mentioned the joystick/alpha lock issue, but the average person probably didn't read all that real thoroughly. 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 8, 2019 Share Posted March 8, 2019 I understand you're talking about the menus, not gameplay. But for gameplay, I don't like joysticks. I have more dexterity in my fingertips on the keyboard. I resent that the Atarisoft games generally don't have keyboard controls. Late games like Barrage and SpotShot let you push Fire instead of Redo. You only needed the keyboard for Back. 2 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 8, 2019 Share Posted March 8, 2019 But you have to consider the times the 99/4A was released in. Most people didn't have computer exposure prior to getting one, and if you just said "Use Joystick to make selection" and you couldn't move up because the Alpha Lock key was engaged, and didn't provide a reminder message, the novice user would likely be pretty frustrated with your program very quickly. I know there was an addendum thing in the pile of docs that came with the 99/4A that mentioned the joystick/alpha lock issue, but the average person probably didn't read all that real thoroughly. In Bubble Plane (1988) I added a CRU bit test and a message saying "RELEASE ALPHA LOCK TO BEGIN PLAY". Despite what I just said, keyboard and joystick gameplay and menus (including joystick high score initials entry) were both supported. 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.