+Vorticon Posted September 12, 2015 Author Share Posted September 12, 2015 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... Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 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)? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 16, 2015 Share Posted December 16, 2015 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 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 Thanks! Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 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? Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 16, 2015 Share Posted December 16, 2015 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. Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 16, 2015 Share Posted December 16, 2015 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 ; Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 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 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! Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 16, 2015 Share Posted December 16, 2015 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. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 16, 2015 Share Posted December 16, 2015 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 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 Thanks for the clarifications guys. One thing about using v@ drop instead of LIMI 2 LIMI 0: isn't the latter a faster way of cycling the interrupts? Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 16, 2015 Share Posted December 16, 2015 (edited) 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! Edited December 16, 2015 by Willsy 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 16, 2015 Share Posted December 16, 2015 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) Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 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 Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 16, 2015 Share Posted December 16, 2015 Okay, cool. So, clearly, there's enough VDP access going on (updating the sprites, frames, patterns, etc) to keep "pumping" the VDP interrupts often enough, so it works. It would probably work with speech too. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 I may have spoken too soon. I seem to be getting random hangups during gameplay which I suspect are related to the interrupts. I'll look more closely into it. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 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... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 16, 2015 Share Posted December 16, 2015 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 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 16, 2015 Author Share Posted December 16, 2015 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... Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 17, 2015 Share Posted December 17, 2015 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. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 17, 2015 Author Share Posted December 17, 2015 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? Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 17, 2015 Share Posted December 17, 2015 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; } Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 17, 2015 Share Posted December 17, 2015 (edited) 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 December 17, 2015 by Tursi Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 17, 2015 Share Posted December 17, 2015 You can do what @Tursi suggested by using TF's SOUND for each channel and devising a VDP-interrupt counting mechanism for the duration times. ...lee Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted December 17, 2015 Author Share Posted December 17, 2015 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 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.