Jump to content
IGNORED

General Turbo Forth questions


Vorticon

Recommended Posts

 

That should work; but, it's convoluted! It's simpler to do this:

 

1 KMODE !

 

The variable, however, appears to not be functioning as \documented. The value I get from KMODE after booting up is 1280—not 5! @Willsy is gonna have to weigh in on this one.

 

...lee

 

Yes of course :) As for the variable itself, that was my thought too...

Link to comment
Share on other sites

  • 3 months later...

So I want to enable to enable and disable interrupts in TF. Easy enough, using ASM: InterruptsOff 0 LIMI, ;ASM and ASM: InterruptsOn 2 LIMI, ;ASM

The problem is that I'd like to use the compiled result in a CODE word so I don't have to load the assembler from disk. How do I get the compiled hex data from the above (or for any other assembly word I create)?

Link to comment
Share on other sites

So I want to enable and disable interrupts in TF. Easy enough, using ASM: InterruptsOff 0 LIMI, ;ASM and ASM: InterruptsOn 2 LIMI, ;ASM

The problem is that I'd like to use the compiled result in a CODE word so I don't have to load the assembler from disk. How do I get the compiled hex data from the above (or for any other assembly word I create)?

 

The UTILS menu is your friend. You want the ASM>CODE utility. It will output the CODE: ... ;CODE definition to a file, which, of course, can be CLIP (the Windows clipboard). Since the utility appends to the file/clipboard, you can define several ALC words and accumulate their CODE: ... ;CODE definitions in the same file/clipboard:

 

ASM: InterruptsOff 0 LIMI, ;ASM

ASM: InterruptsOn 2 LIMI, ;ASM

ASM>CODE InterruptsOff CLIP

ASM>CODE InterruptsOn CLIP

will put the following code in the Windows clipboard:

 

CODE: InterruptsOff
0300 0000 ;CODE
CODE: InterruptsOn
0300 0002 ;CODE

...lee

Link to comment
Share on other sites

I've been trying to play sounds from sound lists in TF, but it's not working. Here's the code:

hex
\ Enhanced DATA code
CODE: data[] ( -- addr #cells )
C073 0644 C503 0644 C501 0A11 A0C1 ;CODE

decimal

variable _state

: data[ ( -- here )
  state @ _state !  state 0!  1 $A068 !
  _state @ if compile data[] here 0 , else here then 
; immediate
 
: ]data  ( here -- )
  dup here swap - 2/ _state @ if 1- swap ! then
  $A068 0!  _state @ state !
; immediate

hex 

\ Sound effects data
: SndGrabFuel ( -- addr #cells )
	data[ 0385 0690 0102 8F08 0102 8506 0101 9F00 ]data ;       

: SndMonsExplode ( -- addr #cells )
	data[ 05C7 09DF E7F0 0101 FA01 05C7 09DF E7F0
		  0101 FA01 05C7 09DF E7F0 0101 FA01 019F 0000
		]data ;
		
\ Interrupts routines
CODE: InterruptsOn                                             
0300 0002 ;CODE      
                                          
CODE: InterruptsOff                                            
0300 0000 ;CODE                                                
	
\ Sound generation routine

: PlaySound ( sound_list -- )
	1000 -rot 2 * vmbw \ load sound list into VDP sound buffer @ >1000
	InterruptsOff
	10 83CC c! 0 83CD c! \ place VDP sound buffer address in >83CC
	83FD c@ 1 or 83FD c! \ set least significant bit of >83FD - VDP sound buffer loaded
	1 83CE c! \ place 1 in >83CE - start sound processing
	InterruptsOn
	begin 83CE c@ 0= until ; \ loop until processing done i.e >83CE is 0
	
decimal

>83CE is supposed to be used as a countdown timer by the ISR during sound execution, but its value remains at one which indicates that the sound processing is not starting. What am I missing here?

Link to comment
Share on other sites

There's a couple of things:

 

  • Sprite auto-motion, sound-list processing and the QUIT key are all disabled by writing >8000 to >83C2
  • Other locations in PAD ram may need to be set up that aren't - or (worse) have TF code in them

See the PAD RAM memory map on the web site.

 

I'll see what I can figure out over the next couple of days.

Link to comment
Share on other sites

The attached plays the sounds, but the explosion doesn't sound right. Is the sound list data correct?

 

Also, is the grab fuel sound correct? If so, no real point in using a sound list for that! Just use SOUND with a short delay.

 

Have you seen these rather funky sound commands? You can do cool stuff with loops.

 

Nayway, here's the code. I removed the machine code LIMI 0 and LIMI 2 stuff, because it's not really needed. Most VDP accesses in TF trigger vdp interrupts, so putting V@ in your loop is enough (V@ does a LIMI 2/LIMI 0 internally).

 

 

hex
\ Sound effects data
: SndGrabFuel ( -- addr #cells )
 data[ 0385 0690 0102 8F08 0102 8506 0101 9F00 ]data ;      
: SndMonsExplode ( -- addr #cells )
 data[ 05C7 09DF E7F0 0101 FA01 05C7 09DF E7F0
    0101 FA01 05C7 09DF E7F0 0101 FA01 019F 0000
  ]data ;
 
\ Sound generation routine
: PlaySound ( sound_list -- )
 1000 -rot 2 * vmbw      \ load sound list into VDP sound buffer @ >1000
 1000 83CC !             \ place VDP sound buffer address in >83CC
 83FD c@ 1 or 83FD c!    \ indicate VDP sound buffer loaded
 1 83CE c!               \ place 1 in >83CE - start sound processing
 40 83c2 c!              \ enable ISR engine for sound lists
 begin 0 v@ drop 83CE c@ 0= until \ loop until processing done i.e >83CE is 0
    8000 83c2 !             \ disable all ISR routines
    ;
Link to comment
Share on other sites

My routine simply follows the instructions and examples given in the EA manual under the sound section :)

Regarding interrupts, my understanding was that interrupts had to be disabled while setting up memory for sound operations. Am I to assume then that interrupts are normally disabled by default in TF? Also there is no mention of location >83C2 in the EA manual in the sound section, yet it seems that setting it up was necessary for sound generation here. Am I correct in this?

In looking at the VDP RAM usage by TF, it looks like the sprite pattern table is at >1000, so the sound buffer will need to be moved higher up in memory. I am using 22 sprites, so I should relocate the buffer above >1400.

 

As for the sound lists, I got those from OLD CS1. I am shamelessly tone deaf, and so he kindly agreed to create the sound effects for Jet Pac to match as closely as possible the original game. Surprisingly, there seems to be a lot more complexity in the Jet Pac sounds than initially meets the eye (or ear...). I suppose I could translate his data into Sound statements, but I wanted to have a better understanding of sound generation on the TI at a lower level :D

There is definitely something wrong with the monster explosion sound as it seems to loop endlessly, so I'll have to check the list. The fuel grab sound is very close to the original.

 

Willsy, once again many thanks!

Link to comment
Share on other sites

Hiya. Yes interrupts are normally disabled in TF. However the speech routines in TF are interrupt driven. TF only enables interrupts during vdp access (strictly speaking, just before the vdp access takes place). Thus you need to 'pump' the vdp to ensure that the ISR runs. Speech is really only used in games which hammer the vdp anyway so it's never been a problem. Not yet anyway.

 

83C2 is a flag to the TI OS which enables specific portions of the ISR. You can disable sprite motion, sound list processing, and the quit key. By default TF turns them all off so that the ISR in ROM returns as fast as possible to TF.

Link to comment
Share on other sites

Regarding >83C2 setup not being mentioned in the sound section of the E/A manual, >83C2 is normally 0 when the E/A cartridge starts up a program. It would certainly have been useful for the authors to have mentioned it in that section because the user can certainly change it.

 

Regarding interrupts in TF, they are indeed normally disabled. Just so you know, interrupts are normally enabled in fbForth to allow user ISRs.

 

...lee

Link to comment
Share on other sites

Absolutely. I was just thinking about saving space (as usual ;) ). But there's no doubt your approach would be much faster.

 

I should really have a look at getting TF to run with interrupts enabled (or, at least give the option). Last time I tried that (a looooong time ago) it crashed everything so hard I had to have a little look out the window to make sure the universe was still okay.

 

That's how hard it crashed! :grin:

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

 

KMODE is a variable and typing it puts its address on the stack.

 

...lee

 

So how does one set the keyboard mode in TF? The online reference states that KMODE places the address of the keyboard mode variable on the stack, but does not give any further details. I wanted to change the mode to 1 (split keyboard), so I entered

KMODE 1 SWAP !

and I got no errors. However, the keyboard mode remained in the default 5 (BASIC mode). What am I doing wrong here?

 

 

1 KMODE SWAP !

 

**edit**

 

Cancel that...

 

KMODE is a variable. I thought KMODE popped a number off the stack, THEN acted upon it.

 

 

 

That should work; but, it's convoluted! It's simpler to do this:

 

1 KMODE !

 

The variable, however, appears to not be functioning as documented. The value I get from KMODE after booting up is 1280—not 5! @Willsy is gonna have to weigh in on this one.

 

...lee

 

I see I neglected to answer this one. The answer is that KMODE pushes an address, but the keyboard mode is in the UPPER 8 bits of that address!

 

Gotcha!

 

Try this:

 

kmode @ .

 

You should see 1280. Hmmm...

 

Now try this:

 

kmode @ $.

 

You'll see 500. In other words, 5 in the high byte and 0 in the lower byte (the display suppresses leading zeros unless you override it with true zeros !)

 

I've updated the language reference page for that one, as it's sure to catch others (including me, since my brain is fried) :D

Link to comment
Share on other sites

I changed the routine a bit because waiting for the sound processing to complete was slowing the game down. I reinstated the interrupt routines, turning them on when sound is started, and checking in the main game loop if >83CE is equal to zero at which point I turn them off along with disabling all the ISR routines. It works great.

: PlaySound ( sound_list -- )
	1500 -rot 2 * vmbw      \ load sound list into VDP sound buffer @ >1500
	1500 83CC !             \ place VDP sound buffer address in >83CC
	83FD c@ 1 or 83FD c!    \ indicate VDP sound buffer loaded
	1 83CE c!               \ place 1 in >83CE - start sound processing
	40 83c2 c! InterruptsOn ;   \ enable ISR engine for sound lists and interrupts
Link to comment
Share on other sites

This is really problematic. TF seems to behave very erratically when interrupts are enabled, and the only way I have been able to consistently mitigate the issue is by waiting for the sound to be processed before continuing on with the program. Unfortunately this slows down the game very noticeably when sound effects are playing, leading to very jerky gameplay.

One option I'm going to explore later today is manually turning interrupts off at the beginning of critical routines and turning them back on afterwards, and then checking once per main game loop pass if sound processing is done and shutting down the ISR engine. This is going to be clunky at best, but it's worth a try...

Link to comment
Share on other sites

Yeah...TF expects interrupts to be disabled for nearly all of the time. The only enabling of interrupts is during VDP accesses and only briefly with LIMI 2, LIMI 0. That is, as soon as there is VDP access, interrupts will be disabled unconditionally, even if you enabled them, I believe.

 

...lee

Link to comment
Share on other sites

That seems to be the case unfortunately. I have resigned myself to waiting for the sound processes to complete before resuming the game as I was unable to find another suitable solution. One thing I have asked OLD CS1 to look into is whether we can shorten some of the sounds a bit so as to minimize the delays. We'll see...

Link to comment
Share on other sites

You can just play the sound list yourself? The format is very simple, all you need is a way to check new data at a fixed rate. If you can't use the VDP Status bit (I don't know if TF manages it), you can still call it in your main loop, you just might have to adjust your durations if your loop runs faster than the VDP interrupt. :)

Link to comment
Share on other sites

There might actually be a solution to the interrupt problem which is to load the sound lists without the duration data directly into the sound processor at address >8400 per the EA manual. This is not dependent on the interrupts and only requires manual control of the duration of each sound in the program. Unfortunately no other details are given in the EA manual and no examples either regarding this alternate method, and I wonder if anyone here has ever used it. I'm not too clear as to the process of loading the list to >8400. Are there timing considerations? Do I load each sound in the list byte by byte, insert a delay for the duration, and then move on to the next sound in the list?

Link to comment
Share on other sites

It's C, but this is the code I use to play simple playlists (no looping, etc). I call this once per frame (my code is usually synced to the VDP blank). I wrote this for porting to the ColecoVision since it didn't have the sound list code. ;)

 

void doMusic() {
  int i,size;

  // pMus is a global that points to the sound list (>83CC)
  if (0 == pMus) {
    return;
  }
  
  // nMusCnt is a global that contains the countdown value (>83CE)
  nMusCnt--;
  if (nMusCnt > 0) {
    return;
  }

  // this function just sets up VDP for a read address,
  // because VDP RAM is where the music is stored
  cv_set_read_vram_address(pMus);

  // this function reads a byte from VDP
  // In this case, it's the number of bytes to load this frame
  i=cv_vinb();
  size=i;

  // zero means end of sound list
  if (i == 0) {
    // clear the music pointer so we stop playing
    pMus=0;
    return;
  }

  // else count down.
  // audport is the address of the sound chip (>8400)
  // cv_vinb() again, reads a byte from VDP RAM
  // This copies all the bytes in this frame to the sound chip
  while ((i--) > 0) {
    audport=cv_vinb();
  }

  // this reads the new countdown value
  nMusCnt=cv_vinb();
  
  // this updates the music pointer
  pMus+=size+2;
}
Link to comment
Share on other sites

There might actually be a solution to the interrupt problem which is to load the sound lists without the duration data directly into the sound processor at address >8400 per the EA manual. This is not dependent on the interrupts and only requires manual control of the duration of each sound in the program. Unfortunately no other details are given in the EA manual and no examples either regarding this alternate method, and I wonder if anyone here has ever used it. I'm not too clear as to the process of loading the list to >8400. Are there timing considerations? Do I load each sound in the list byte by byte, insert a delay for the duration, and then move on to the next sound in the list?

Yeah... I found that part of the E/A manual terribly confusing for years. The sound chip doesn't take sound lists. All it takes is single byte commands which specify a channel and either a frequency code or a volume code.

 

You posted while I was still commenting the above code, so I hope it helps a little, but basically, yeah. You would divide your sound list into blocks separated by the duration bytes. You load all the bytes in one block and then wait for the number of VDP interrupts specified by the duration. Repeat until the block length is specified as 0, then you're done.

Edited by Tursi
Link to comment
Share on other sites

Yeah... I found that part of the E/A manual terribly confusing for years. The sound chip doesn't take sound lists. All it takes is single byte commands which specify a channel and either a frequency code or a volume code.

 

You posted while I was still commenting the above code, so I hope it helps a little, but basically, yeah. You would divide your sound list into blocks separated by the duration bytes. You load all the bytes in one block and then wait for the number of VDP interrupts specified by the duration. Repeat until the block length is specified as 0, then you're done.

 

Thanks for the info. That's a big help. I'm flying out tonight, so this may have to wait till after Christmas unless I can sneak in a few lines of code on the plane rides :)

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