Jump to content
IGNORED

Assembly on the 99/4A


matthew180

Recommended Posts

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 :P

 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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 *R3since 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!

Link to comment
Share on other sites

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 )".)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

 

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 :P

 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!

Link to comment
Share on other sites

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

  • Like 3
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

 

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...

Link to comment
Share on other sites

 

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

Link to comment
Share on other sites

 

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.

Link to comment
Share on other sites

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

  • Like 2
Link to comment
Share on other sites

 

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

Link to comment
Share on other sites

 

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?

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...