+Vorticon Posted January 14, 2018 Share Posted January 14, 2018 I've attached a corrected version. Thank you! I can confirm that it does work. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 14, 2018 Share Posted January 14, 2018 Is it safe to stash data in the scratch pad from >8300 to >8349? I've loaded data from >8300 to >8340, but after that the program just freezes. I can verify that the data loaded fine in the debugger. The EA manual states that the area can be used by the programmer, but clearly there are issues... My thinking was to load the data in scratch pad, then do an AORG to the first data element and overwrite it with the rest of the code. Since the assembly is line by line, this should technically work and save me over 50 bytes. Another option is to use the sprite attribute table as storage as long as I place a D0 at the beginning to inactivate sprites, but it involves using the VDP utilities which are slow... OK that's dumb... If I overwrite the data then when the program runs it won't have any data to load into the scratch pad! I need a break LI R1,>8300 LI R3,>7DC8 --> address of first DATA element LI R2,32 MOV *R3+,*R1+ DEC R2 JNE $-6 DATA >7FB2,>77BA DATA >87BA,>7FB2 DATA >469B,>3B9B DATA >46A6,>469B DATA >2F63,>275B DATA >276B,>2F63 DATA >462A,>461F DATA >3B2A,>462A DATA >7E13,>860A DATA >760B,>7E13 DATA >B72A,>C22A DATA >B71F,>B72A DATA >CE63,>D66B DATA >D65B,>CE63 DATA >B79B,>B7A6 DATA >C29B,>B79B CLR R0 ----->>> Program hangs here MOVB R0,@>8374 CLR R6 PL LI R7,1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 14, 2018 Share Posted January 14, 2018 I dare say the program is not hanging where you say it is because the next statement executed after “JNE $-6” fails is the first datum following it! You should follow that statement with “JMP *R3” “B *R3”since R3 should now be pointing there. ...lee 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted January 14, 2018 Share Posted January 14, 2018 you're always in a more comfortable situation with Classic 99, since it is a TI-99/4A-only emulator, and you can assume safe ways to retrieve meta-information (what is the system doing) and to monitor activity. I understand your situation, but it's a little trivializing (and not exactly true) to say that, since the first suggestion I made to you is /not/ part of Classic99. It's real hardware attached to real TI-99/4A machines. There is no "safe way to retrieve meta-information" because it's not attached to any part of the computer's hardware except the keyboard interface port. (That I later included it in Classic99 does not change that - Classic99 emulates the PC keyboard layout by emulating a real adapter. ) It works because we know how the keyboard port works and it works in Classic99 because the port is emulated to the bit level, not because we're making assumptions. I'm sure if you think about how the Geneve port works you can think of a way to gate it externally as well. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 14, 2018 Share Posted January 14, 2018 I dare say the program is not hanging where you say it is because the next statement executed after “JNE $-6” fails is the first datum following it! You should follow that statement with “JMP *R3” “B *R3”since R3 should now be pointing there. ...lee Of course... I think I've been at this too long today. Using the LBLA is so different from the E/A it sometimes confuses me... Thank you Lee! Quote Link to comment Share on other sites More sharing options...
+mizapf Posted January 14, 2018 Share Posted January 14, 2018 Ah, I may have misunderstood how your device works. When it is a real piece of hardware - as you say - there is a way to emulate it. :-) There is actually a string paste function in the PS/2 adapter I created -- which is a separate piece of hardware that needs to interface to a real TI. All you need to do is count how many times the column changes. When it has changed as many times as there are possible columns (I believe I used 8 ) you can be reasonably sure that at least one scan has completed. True that this is not 100% and software could be written that it's not compatible with -- but this software is very unlikely to be able to receive a generic pasted string. My code uses this sequence to establish a 'frame'. It holds the character being pasted for one frame, then it leaves the keys off for one frame. This means it pastes at the rate that the calling software is scanning the keyboard (possibly slightly slower). I first thought you referred to screen columns, but you're talking about keyboard columns, don't you? (It's partly the fault of the forum software, creating that smiley, so I thought you wrote 28, but I guess this was "8 )".) Quote Link to comment Share on other sites More sharing options...
RXB Posted January 15, 2018 Share Posted January 15, 2018 Ah, I may have misunderstood how your device works. When it is a real piece of hardware - as you say - there is a way to emulate it. :-) I first thought you referred to screen columns, but you're talking about keyboard columns, don't you? (It's partly the fault of the forum software, creating that smiley, so I thought you wrote 28, but I guess this was "8 )".) I freaking hate the Smiley face being used for a normal keyboard character. The idea is beyond stupid. Quote Link to comment Share on other sites More sharing options...
Willsy Posted January 15, 2018 Share Posted January 15, 2018 Is it safe to stash data in the scratch pad from >8300 to >8349? I've loaded data from >8300 to >8340, but after that the program just freezes. I can verify that the data loaded fine in the debugger. The EA manual states that the area can be used by the programmer, but clearly there are issues... My thinking was to load the data in scratch pad, then do an AORG to the first data element and overwrite it with the rest of the code. Since the assembly is line by line, this should technically work and save me over 50 bytes. Another option is to use the sprite attribute table as storage as long as I place a D0 at the beginning to inactivate sprites, but it involves using the VDP utilities which are slow... OK that's dumb... If I overwrite the data then when the program runs it won't have any data to load into the scratch pad! I need a break LI R1,>8300 LI R3,>7DC8 --> address of first DATA element LI R2,32 MOV *R3+,*R1+ DEC R2 JNE $-6 DATA >7FB2,>77BA DATA >87BA,>7FB2 DATA >469B,>3B9B DATA >46A6,>469B DATA >2F63,>275B DATA >276B,>2F63 DATA >462A,>461F DATA >3B2A,>462A DATA >7E13,>860A DATA >760B,>7E13 DATA >B72A,>C22A DATA >B71F,>B72A DATA >CE63,>D66B DATA >D65B,>CE63 DATA >B79B,>B7A6 DATA >C29B,>B79B CLR R0 ----->>> Program hangs here MOVB R0,@>8374 CLR R6 PL LI R7,1 You're executing data as code after the loop finishes! Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 15, 2018 Share Posted January 15, 2018 Yup... Lee pointed that out already Brain was fried... All better now though now that the Vikings have won he he... (American football for the uninitiated) 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 15, 2018 Share Posted January 15, 2018 As I was looking at the scratch pad description in the EA manual, I came across these 2 addresses: >8378: Random number generator >83C0: Random number seed How are these used in assembly? There are no details in the manual... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 15, 2018 Share Posted January 15, 2018 As I was looking at the scratch pad description in the EA manual, I came across these 2 addresses: >8378: Random number generator >83C0: Random number seed How are these used in assembly? There are no details in the manual... I think >8378 is used by the GPL RAND function to return a random byte. I will check on that. <--Yes, this is correct. >83C0 is the console ISR’s R0 and the random number seed for the GPL RAND function used by TI Basic and RXB. It is also the seed for the Pseudo-Random Number Generators of TI Extended Basic, TI Forth, fbForth and TurboForth (I think). Not sure about Camel99 Forth. ...lee 3 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted January 15, 2018 Share Posted January 15, 2018 The E/A manual is precise in most parts, but in the description of PAD, it is weirdly sloppy. Many information only apply when GPL is used or when interrupts are active. For instance, there are addresses 837D,E,F: >837D: The character buffer used by the VDP. It reflects the code loaded in the screen image area of the VDP RAM. Loading a character code at this address results in displaying the character on the screen based on the pointers at address >837E and >837F. >837E: Points to the current row on the screen. >837F: Points to the current column on the screen. Or >83D4: Current value stored in VDP Register 1. I remember this was highly confusing for me when I learned Assembly language. Needless to say, nothing happened when I wrote values to those locations. However, when interrupts are enabled, 83D4 is indeed meaningful, but only when you press a key. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 15, 2018 Share Posted January 15, 2018 I think >8378 is used by the GPL RAND function to return a random byte. I will check on that. <--Yes, this is correct. >83C0 is the console ISR’s R0 and the random number seed for the GPL RAND function used by TI Basic and RXB. It is also the seed for the Pseudo-Random Number Generators of TI Extended Basic, TI Forth, fbForth and TurboForth (I think). Not sure about Camel99 Forth. ...lee So is there a way to access the GPL RAND function from assembly? My guess is probably not... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 15, 2018 Share Posted January 15, 2018 So is there a way to access the GPL RAND function from assembly? My guess is probably not... I am not sure you want to do that. It only returns a single byte. It is used by the TI Basic RND function to get each byte of the floating point number returned by RND. In a little bit, I will post the ALC of the RND , RNDW and RANDOMIZE functions of fbForth 2.0 (from TI Forth) ...lee Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 15, 2018 Share Posted January 15, 2018 I am not sure you want to do that. It only returns a single byte. It is used by the TI Basic RND function to get each byte of the floating point number returned by RND. In a little bit, I will post the ALC of the RND , RNDW and RANDOMIZE functions of fbForth 2.0 (from TI Forth) ...lee Actually a single byte is perfect! All I need is a number that (pseudo)randomly varies which I can check for even or odd. Problem is when I look in the debugger in Classic99, that memory location does not change and I don't know how to activate it... I only have 220 bytes or so left to work with, and I don't have room for a full blown random routine unfortunately. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted January 15, 2018 Share Posted January 15, 2018 This is the core of the RAND routine: LI R4,>6FE5 MPY @>83C0,R4 AI R5,>7AB9 MOV R5,@>83C0 The rest of the routine in the console simply calculates R5 mod limit and stores it at 8378. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 15, 2018 Share Posted January 15, 2018 This is the core of the RAND routine: LI R4,>6FE5 MPY @>83C0,R4 AI R5,>7AB9 MOV R5,@>83C0 The rest of the routine in the console simply calculates R5 mod limit and stores it at 8378. The only thing fbForth 2.0 and TI Forth add to that is “SRC R5,5”. Also, TI Basic’s RANDOMIZE grabs the VDP interrupt timer byte (>8379) and jams it in the low byte of >83C0. Whereas, the fbForth 2.0 and TI Forth’s RANDOMIZE count how many times through the S1016A loop it takes to catch the VDP interrupt with the following code with interrupts enabled: MOVB @>8802,R0 get VDP status byte CLR R0 discard it CLR R1 clear counter S1016A INC R1 increment counter MOVB @>8802,R0 get VDP status byte ANDI R0,>8000 VDP interrupt? JEQ S1016A no, increment counter MOV R1,@>83C0 yes, store new seed ...lee 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 16, 2018 Share Posted January 16, 2018 Actually a single byte is perfect! All I need is a number that (pseudo)randomly varies which I can check for even or odd. Problem is when I look in the debugger in Classic99, that memory location does not change and I don't know how to activate it... I only have 220 bytes or so left to work with, and I don't have room for a full blown random routine unfortunately. Well, then—just grab the VDP interrupt timer byte at >8379, which varies cyclically from 0 – 255, 60 times/second in unit increments. ...lee Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 16, 2018 Share Posted January 16, 2018 This is the core of the RAND routine: LI R4,>6FE5 MPY @>83C0,R4 AI R5,>7AB9 MOV R5,@>83C0 The rest of the routine in the console simply calculates R5 mod limit and stores it at 8378. What exactly is happening here? Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 16, 2018 Share Posted January 16, 2018 The only thing fbForth 2.0 and TI Forth add to that is “SRC R5,5”. Also, TI Basic’s RANDOMIZE grabs the VDP interrupt timer byte (>8379) and jams it in the low byte of >83C0. Whereas, the fbForth 2.0 and TI Forth’s RANDOMIZE count how many times through the S1016A loop it takes to catch the VDP interrupt with the following code with interrupts enabled: MOVB @>8802,R0 get VDP status byte CLR R0 discard it CLR R1 clear counter S1016A INC R1 increment counter MOVB @>8802,R0 get VDP status byte ANDI R0,>8000 VDP interrupt? JEQ S1016A no, increment counter MOV R1,@>83C0 yes, store new seed ...lee What's the advantage of Fb forth's method versus simply grabbing the VDP interrupt byte directly as in TI Basic? Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 16, 2018 Share Posted January 16, 2018 Well, then—just grab the VDP interrupt timer byte at >8379, which varies cyclically from 0 – 255, 60 times/second in unit increments. ...lee Yup that would probably work just fine. Do I have to issue a LIMI 2 LIMI 0 pair first? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 16, 2018 Share Posted January 16, 2018 This is the core of the RAND routine: LI R4,>6FE5 MPY @>83C0,R4 AI R5,>7AB9 MOV R5,@>83C0 The rest of the routine in the console simply calculates R5 mod limit and stores it at 8378. What exactly is happening here? The random number seed at >83C0 is used to calculate a pseudo-random number, which becomes the new seed: SEED = SEED * >6FE5 + >7AB9 ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 16, 2018 Share Posted January 16, 2018 What's the advantage of Fb forth's method versus simply grabbing the VDP interrupt byte directly as in TI Basic? TI Basic only changes the low byte of the seed (>83C0), which gives a variation of only 256 possible 16-bit numbers for any given sampling, whereas fbForth theoretically allows for 65535 variations. Realistically, the higher 16-bit numbers will almost never be returned, but the variation is a good deal more than 256. The fbForth calculation of a pseudo-random number (and next seed) also carries the calculation one step further than GPL’s RAND by doing a circular right shift of 5 bits: SEED = (SEED * >6FE5 + >7AB9) src 5 I am not sure why the TI developers of TI Forth added this additional step, but I saw no reason to change it for fbForth. ...lee Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 16, 2018 Share Posted January 16, 2018 Got it. Thanks. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 16, 2018 Share Posted January 16, 2018 Yup that would probably work just fine. Do I have to issue a LIMI 2 LIMI 0 pair first? If interrupts are not enabled regularly somewhere in your program—yes, you would need to do that. Somehow, you need to avoid a regular sampling of the VDP interrupt timer. That is, I would think that cycling interrupts just before sampling the timer might possibly return the same number every time, reflecting instruction timing. You would need to test that. Maybe someone here better-versed on the TMS9900//TI-99/4A than I can shed light on that. ...lee 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.