Jump to content
IGNORED

Assembly on the 99/4A


matthew180

Recommended Posts

It looks like a pile of grass being tucked in there.

 

Back when I did it it wasn't as easy to get a PCB layout manufactured in small quantities as it is today, so I never took the design beyond that. I've not done any feasibility study of whether it's possible to make room for one inside the console. I think some designs on cards in there work, but they have to get rid of the EMC shield inside, don't they?

 

Sorry if this leads us more to mechanical than software assembly...

Link to comment
Share on other sites

Something like the zeno board and others, don't allow for the top shield.

 

It sound like an interesting board you have, I'm sure most TI Enthusiast would be happy to put one in a console, if such a board existed.

 

Fortunately, you can still get consoles for around $65 dollars on ebay.

 

Thanks TI for making these in the millions! 😃

Link to comment
Share on other sites

I have some spare consoles. Maybe I should try to design the thing as a board... Maybe I need to retire first... But that's not too far away!

 

Here's a picture. It's a scan of a color slide, so not that good quality. I have some of better quality, but in these the whole decoding system isn't installed. It was when it was only working as a 32 K RAM expansion, nothing else.

 

The current design has eight CRU bits, each controlling 8 K RAM. The four that control the banks belonging to the 32 K RAM expansion are inverted, so at power up, the internal 32 K RAM expansion is active and the other 32 K are not. If you set all bits, then you get 32 K RAM over internal ROM, DSR space, cartridge space and memory mapped devices like VDP, sound and scratch pad RAM. The internal 32 K RAM expansion is then disabled, so you can "see through" out to 32 K RAM in the expansion box.

Of course you can set each bit individually with SBO/SBZ or LDCR. No hardware for any feedback, so no use for TB nor STCR at CRU address >0400.

 

I decided to not support write-through, as some of the memory areas are used for memory mapped IO. By write-through I mean the function that when the RAM is disabled, you'll read from the ROM, but if you write to ROM, it will reach the RAM even when it's disabled. In such a case you can copy a word from ROM to RAM with MOV @ADDR,@ADDR. What is at ADDR in the ROM will be transferred to ADDR in the RAM. To actually read from the RAM you have to enable it, and then you can't see the ROM any more.

But since VDP and other stuff can be written to, and in some cartridges there's RAM too, I don't allow that. If you write to ROM it's lost. So to copy the ROM in the machine, the simplest method is to enable RAM at >6000->7FFF, copy everything between >0000 and >1FFF to memory starting at >6000, then enable RAM at >0000->1FFF and copy the bank at >6000->7FFF back to the first block. At the end you disable RAM at >6000 but keep it on at >0000. Now you have all the monitor ROM, interrupt vectors included, in RAM and can modify as you like.

 

Obviously enabling RAM over >8000->9FFF will void access to most of the system's resources, so that's something you can use only for special things, like a buffer during a sorting operation or something similar. Or if your program needs a fast secondary storage of some data, accessed in smaller chunks. Then you can enable that bank, read the data to some working memory and close it again. Next time you read a different part of that data to your working memory.

Another application could be to switch all of the 24 K RAM into a buffer. You read in all pixel and color data from a bitmap screen into the first half of that buffer. Then you want to create some transformation pattern and do some math with the original image and that pattern, to create a new image. In such a case you can create the new image in the second half of the 24 K RAM, run your program in the 8 K RAM part and still have room for the transformation pattern between >6000 and >9FFF, as an example. When done you feed the created image buffer at the second half of 24 K RAM back to VDP RAM and turn off your extra memory banks before you return.

Such things are usually possible to do piecemeal but more efficient in big chunks.

 

And you do of course have two layers of 32 K RAM expansion to choose from. My first design enabled the 32 K as one big unit, because I wanted one of the CRU bits to control a hardware slow-down of VDP access, so software not including an extra instruction between certain VDP accesses could still work, in spite of otherwise running in fast memory. But I removed that and redesigned the enabling bits to be one per 8 K RAM, becuase it was more valuable to be able to run a program in 8 K RAM and being able to exchange the three memory banks in the 24 K RAM part individually, for example.

 

The fact that when you turn off the CRU bits, as after a reset, the computer works just normal, with the exception that there is a 16-bit wide memory expansion available in the console, is also very handy. You can still use memory expansion cartridges, RAM disks and such stuff.

Edited by apersson850
  • Like 2
Link to comment
Share on other sites

That looks something similar to the Mike Ballman 32k instruction layout , that were out back in the day. I still have two motherboards that have that mod, but wire have been torn loose due to storage issues. I'd like to find those instructions again and "fix" the rats nest on my boards if possible.

Link to comment
Share on other sites

So here is my code fragment, it's a slight modification of the chime code in the E/A, using data (not shown) I pulled from The Intern for beep.

 

PAT    EQU  $            PLAY ACCEPT TONE
       LI   R0,BUFFER    Load VDP RAM buffer address.
       LI   R1,ACEPTT    Pointer to the sound data.
       LI   R2,11        11 bytes to move to the VDP RAM buffer.
*
       BLWP @VMBW        Move to the VDP RAM - play sound list from VDP RAM
*
       LI R10,BUFFER     Load sound table address.
       MOV R10,@>83CC    Load pointer to the table.
       SOCB @H01,@>83FD  Set VDP flag.
       MOVB @H01,@>83CE  Trigger sound processing.
       LIMI 2            START PROCESSING

LP2    MOVB @>83CE,@>83CE  Check if time is up
       JEQ  SCAN1          DONE PLAYING LEAVE
       JMP  LP2

 

  The books I've read say sound lists can be processed from VDP RAM or CPU RAM.  But, I've only came upon examples of processing a sound list from VDP RAM.

 

  Can someone point me to an example of processing a sound list from CPU RAM?

 

 

Link to comment
Share on other sites

7 hours ago, RickyDean said:

That looks something similar to the Mike Ballman 32k instruction layout , that were out back in the day. I still have two motherboards that have that mod, but wire have been torn loose due to storage issues. I'd like to find those instructions again and "fix" the rats nest on my boards if possible.

This might be what you're looking for.

http://www.mainbyte.com/ti99/16bit32k/32kconsole.html

Link to comment
Share on other sites

24 minutes ago, hhos said:

This might be what you're looking for.

http://www.mainbyte.com/ti99/16bit32k/32kconsole.html

Very similar, but not the same. The Ballman setup had a series of diodes and some straddled IC's to include the Srams. I know that I have those instructions either in print or on old CD's, as I always backup everything I get my hands on.

Here's a picture of the two motherboards I have 

 

 

Thanks though.

Edited by RickyDean
Link to comment
Share on other sites

8 minutes ago, RickyDean said:

Very similar, but not the same. The Ballman setup had a series of diodes and some straddled IC's to include the Srams. I know that I have those instructions either in print or on old CD's, as I always backup everything I get my hands on.

 

Thanks though.

I don't recall it that way. I did the Ballman mod back in the day and there were no diodes (that I recall). Straddled ICs, yes, but that's what you get in the Mainbyte link above. I'd be surprised if yours didn't match up (and would love a photo, maybe we can reverse what it was for you ;) )

 

Edited by Tursi
Link to comment
Share on other sites

4 minutes ago, Tursi said:

I don't recall it that way. I did the Ballman mod back in the day and there were no diodes (that I recall). Straddled ICs, yes, but that's what you get in the Mainbyte link above. I'd be surprised if yours didn't match up (and would love a photo, maybe we can reverse what it was for you ;) )

 

The post above gives a link to the photos in 2016 of the two boards. It can get you started. I would have to hunt those boards down currently to get better pics of them.

Link to comment
Share on other sites

After going back and reading the thread I found that Mark Hull, answered my question. The 32k console with the diodes were shown in MicroPendium March edition, pg 35. This was probably the one I used on that board, though my instructions were probably form someone in the HUG or from the Chicago BBS? Back to Assembly!

 

32k console.jpg

Edited by RickyDean
  • Like 1
Link to comment
Share on other sites

1 hour ago, RickyDean said:

The post above gives a link to the photos in 2016 of the two boards.

There are two styles of mod in that photo. The top has diodes, and appears to be a one chip 8-bit mod. The bottom does not, and appears a close match to the MainByte 16-bit mod. For reference, my mod (photo above) followed MainByte instructions and diagrams (right down to the colors). 

Edited by Reciprocating Bill
Link to comment
Share on other sites

9 minutes ago, Reciprocating Bill said:

There are two styles of mod in that photo. The top has diodes, the bottom does not, but rather appears a close match to the MainByte mod. For reference, my mod (pnoto above) followed MainByte instructions and diagrams (right down to the colors). 

Yep, the top was done in the mid 90's, the bottoms a few years after, so the instructions would have probably come from somewhere else.

Link to comment
Share on other sites

4 hours ago, dhe said:

So here is my code fragment, it's a slight modification of the chime code in the E/A, using data (not shown) I pulled from The Intern for beep.

 

PAT    EQU  $            PLAY ACCEPT TONE
       LI   R0,BUFFER    Load VDP RAM buffer address.
       LI   R1,ACEPTT    Pointer to the sound data.
       LI   R2,11        11 bytes to move to the VDP RAM buffer.
*
       BLWP @VMBW        Move to the VDP RAM - play sound list from VDP RAM
*
       LI R10,BUFFER     Load sound table address.
       MOV R10,@>83CC    Load pointer to the table.
       SOCB @H01,@>83FD  Set VDP flag.
       MOVB @H01,@>83CE  Trigger sound processing.
       LIMI 2            START PROCESSING

LP2    MOVB @>83CE,@>83CE  Check if time is up
       JEQ  SCAN1          DONE PLAYING LEAVE
       JMP  LP2

 

  The books I've read say sound lists can be processed from VDP RAM or CPU RAM.  But, I've only came upon examples of processing a sound list from VDP RAM.

 

  Can someone point me to an example of processing a sound list from CPU RAM?

 

 

Which books are those?
My understanding is that the ISR PLAYER, expects sound lists to be in VDPRAM/GROM, 9/8 @>83FD.

:ponder:If anyone would know... @Lee Stewart

Link to comment
Share on other sites

5 hours ago, RickyDean said:

After going back and reading the thread I found that Mark Hull, answered my question. The 32k console with the diodes were shown in MicroPendium March edition, pg 35. This was probably the one I used on that board, though my instructions were probably form someone in the HUG or from the Chicago BBS? Back to Assembly!

ooh, it's a 1 chip one! Thanks for linking that. :)

 

  • Like 1
Link to comment
Share on other sites

10 hours ago, RickyDean said:

After going back and reading the thread I found that Mark Hull, answered my question. The 32k console with the diodes were shown in MicroPendium March edition, pg 35.

I found it. The year was 1991.

10 hours ago, RickyDean said:

Back to Assembly!

Still this is a bit relevant in an assembly thread, since it opens up more possibilities, and they are accessible from assembly only.

 

Most users having the desire to add the memory expansion inside the console already had the standard 32 K RAM expansion. My project was inspired by an article in the Canadian R/D Computing (Ryte Data), Vol 2, ver 25, 1987. They added 64 K RAM to get the same 32 K RAM as they already had, just faster.

Another article posted the idea to add a switch so that you could slow down the internal RAM to the same speed as external RAM, for compatibility reasons. Still 32 K.

Then another article in the German TI Revue had the idea to do a hardware delay of the VDP, so graphics would work even with fast memory. Still 32 K.

To that I added my own idea of making the whole 64 K accessible at the same time as it was possible to get contiguous 64 K RAM in the machine. So, install 64 K and get 64 K.

Finally I realized that it would also be possible to disable the internal expansion and thus reach the external one, provided it was still there. Even better deal - add 64 K and get 96 K.

 

If you write an assembly only program, then you can of course do whatever you like. But in the more common applications, supporting a higher level language, you can do like this:

  • If called from Extended BASIC, you know your code is running in the 8 K RAM. Then you can switch in a different RAM bank in the 24 K RAM and easily use that memory block for data when your program is running.
  • If called from Pascal, your code is somewhere in 24 K RAM. Then you can switch in the first 32 K of RAM to have your data there, in one large block.

Most likely there is some, but to this day I've not seen anybody else publishing this particular (or similar) bank switching method to make an internal memory expansion more flexible.

 

Going back to assembly, I can add that the PME on the p-code card (Pascal) has it's own versions of how to automatically move sprites (accessed by uses sprite) and how to play music (accessed by uses sound or the simpler uses beep).

The sound list player included in the unit sound is pretty complex. You can:

  • Create any number of sound lists of any length.
  • Discard lists when not needed, to recover the memory they occupied.
  • Store sequences of tones, notes or noise in the lists.
  • Create branches and subroutine calls inside lists, to play repeating parts.
  • Store sound lists on disk, and read them back, of course.
  • Set flags in sound lists, flags that can be checked to see how far the list has played, to synchronize with your program.
  • Associate a list with a tone generator.
  • Play any (or all) of the tone generators.

Details are in section 6.4 of the Pascal compiler manual, if anyone wants inspiration about ways to handle sound.

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

15 hours ago, dhe said:

So here is my code fragment, it's a slight modification of the chime code in the E/A, using data (not shown) I pulled from The Intern for beep.

 

PAT    EQU  $            PLAY ACCEPT TONE
       LI   R0,BUFFER    Load VDP RAM buffer address.
       LI   R1,ACEPTT    Pointer to the sound data.
       LI   R2,11        11 bytes to move to the VDP RAM buffer.
*
       BLWP @VMBW        Move to the VDP RAM - play sound list from VDP RAM
*
       LI R10,BUFFER     Load sound table address.
       MOV R10,@>83CC    Load pointer to the table.
       SOCB @H01,@>83FD  Set VDP flag.
       MOVB @H01,@>83CE  Trigger sound processing.
       LIMI 2            START PROCESSING

LP2    MOVB @>83CE,@>83CE  Check if time is up
       JEQ  SCAN1          DONE PLAYING LEAVE
       JMP  LP2

 

  The books I've read say sound lists can be processed from VDP RAM or CPU RAM.  But, I've only came upon examples of processing a sound list from VDP RAM.

 

  Can someone point me to an example of processing a sound list from CPU RAM?

 

 

I ASSUMMED that if you reset the VDP bit in >83FD  you could play lists from CPU RAM but I just tried it and it didn't work with my code.

  • Like 2
Link to comment
Share on other sites

18 hours ago, dhe said:

So here is my code fragment, it's a slight modification of the chime code in the E/A, using data (not shown) I pulled from The Intern for beep.

 

PAT    EQU  $            PLAY ACCEPT TONE
       LI   R0,BUFFER    Load VDP RAM buffer address.
       LI   R1,ACEPTT    Pointer to the sound data.
       LI   R2,11        11 bytes to move to the VDP RAM buffer.
*
       BLWP @VMBW        Move to the VDP RAM - play sound list from VDP RAM
*
       LI R10,BUFFER     Load sound table address.
       MOV R10,@>83CC    Load pointer to the table.
       SOCB @H01,@>83FD  Set VDP flag.
       MOVB @H01,@>83CE  Trigger sound processing.
       LIMI 2            START PROCESSING

LP2    MOVB @>83CE,@>83CE  Check if time is up
       JEQ  SCAN1          DONE PLAYING LEAVE
       JMP  LP2

 

  The books I've read say sound lists can be processed from VDP RAM or CPU RAM.  But, I've only came upon examples of processing a sound list from VDP RAM.

 

  Can someone point me to an example of processing a sound list from CPU RAM?

 

 

I've attached (hopefully) the source for TI Invaders which uses sound lists in CPU RAM. There is a "CALL SOUND" routine (search for it) that I can see includes a couple of the lines you have above. May or may not be useful ...

 

OOPS - NO - IGNORE ... missed that the sound lists actually get written to VDP RAM. 🤫

 

TI Invaders (Disk Version).a99

Edited by Stuart
  • Like 3
Link to comment
Share on other sites

On 2/2/2024 at 6:15 PM, dhe said:

  The books I've read say sound lists can be processed from VDP RAM or CPU RAM.  But, I've only came upon examples of processing a sound list from VDP RAM.

 

  Can someone point me to an example of processing a sound list from CPU RAM?

 

On 2/2/2024 at 10:47 PM, HOME AUTOMATION said:

Which books are those?
My understanding is that the ISR PLAYER, expects sound lists to be in VDPRAM/GROM, 9/8 @>83FD.

:ponder:If anyone would know... @Lee Stewart

 

On 2/3/2024 at 12:15 AM, FarmerPotato said:

@HOME AUTOMATION The short answer is: you write your own code for sound list player.   Then put that address as the User ISR. 

 

If you are using the console ISR to process sound lists, they must be located in VRAM or GROM/GRAM as @HOME AUTOMATION said. The examples in “Chapter 20” of the E/A Manual use VRAM. For VRAM, the LSb of >83FD must be 1 and for GROM/GRAM, it must be 0. >83FD is the GPL flag byte for 5 flags that occupy the 5 rightmost bits. You should not mess with the other flags. They have to do with cassette, multicolor settings, and VRAM. 8 indicates 16 KiB VRAM.

 

If you want the list in CPU RAM, then you must write your own sound list processor as @FarmerPotato said.

 

For fbForth, I wrote my own (starting with @Willsy’s TurboForth implementation), which is serviced by the fbForth ISR. You are welcome to the code, but it may be difficult to understand without a lot of explanation.

 

...lee

 

Edited by Lee Stewart
credits
  • Like 5
  • Thanks 1
Link to comment
Share on other sites

53 minutes ago, Vorticon said:

Is there way to use a non-absolute displacement for SBO, SBZ and TB? I've tried a couple of ways, using a register and a memory location containing a displacement but I got an assembler error.

 

Change the value in R12 ?

As far as I know you can move R12 and then use SBO 0  SBZ 0 

So you could make different EQUates for R12 contents to set the different base address/es you want to work on. 

This might not be considered good practice but you know ...

 

  • Like 1
Link to comment
Share on other sites

9 minutes ago, TheBF said:

Change the value in R12 ?

As far as I know you can move R12 and then use SBO 0  SBZ 0 

So you could make different EQUates for R12 contents to set the different base address/es you want to work on. 

This might not be considered good practice but you know ...

 

Brilliant! I'll test it out.

Link to comment
Share on other sites

15 hours ago, TheBF said:

Change the value in R12 ?

As far as I know you can move R12 and then use SBO 0  SBZ 0 

So you could make different EQUates for R12 contents to set the different base address/es you want to work on. 

This might not be considered good practice but you know ...

 

14 hours ago, Vorticon said:

Brilliant! I'll test it out.

 

Just remember that CRU bits in R12 are offset 1 bit left, i.e., you should double any bits you add to R12. For example, if you want to set bit 5 of CRU >1D00, You would set R12 to >1D0A and use “SBO 0” to set it. That way you can always use the same SBO instruction without knowing the CRU bit at assembly time. This is actually the way it is done in fbForth (inherited from TI Forth).

 

...lee

  • Like 3
Link to comment
Share on other sites

33 minutes ago, Lee Stewart said:

 

 

Just remember that CRU bits in R12 are offset 1 bit left, i.e., you should double any bits you add to R12. For example, if you want to set bit 5 of CRU >1D00, You would set R12 to >1D0A and use “SBO 0” to set it. That way you can always use the same SBO instruction without knowing the CRU bit at assembly time. This is actually the way it is done in fbForth (inherited from TI Forth).

 

...lee

Ah thanks! You just saved me from a lot of hair pulling... So it is a kosher way of doing things after all...

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