senior_falcon Posted March 24, 2022 Share Posted March 24, 2022 (edited) Over the past few days I have been working with PixelPedant, trying to use the routines in the "Text to Speech" disk in a compiled program. I found that CALL INIT and CALL LOAD("DSK3.SPEAK") or CALL LOAD("DSK3.XLAT") will crash XB 2.9 G.E.M., although they load fine in standard XB. For XB 2.9 G.E.M. the crash happens from a write to >7FFE which selects a non-existant rom bank. XB 2.9 G.E.M. uses the MiniMemory loader adapted to the XB environment. Turns out that CALL INIT and CALL LOAD("DSK3.SPEAK") will crash MiniMemory BASIC as well. Below are a few lines of code from the MiniMem loader and below that is a screen from the Classic99 debugger. (This was done from MiniMemory BASIC) The breakpoint is the first time the loader came to >64B4. You can see the loop will continue until R9=0 which overwrites almost the entire ram. A disassembly of the MiniMemory rom and the SPEAK file are included below. Can anyone shed some light as to: What is it about the SPEAK and XLAT files that causes them to behave differently when loading from XB and MiniMemory? Is there a fix for this? (edit) I should add that E/A BASIC gives an "ILLEGAL TAG" error message when trying to load SPEAK, so there is yet another behavior. You can look at >8300 with the debugger and see that the pad is trashed by MiniMemory and XB 2.9 G.E.M. when loading SPEAK. E/A does NOT trash the pad. MINIMEMROM.txt SPEAK MOV 6,9 shift symbol table to remove ref S 4,9 number of bytes to shift MOV 6,10 source= undef label) AI 10,>0008 dest= next label upwards MOV 6,3 source ptr A64B4 DECT 3 DECT 10 MOV *3,*10 copy 1 word 8 bytes above DECT 9 A64BC JNE A64B4 more to do AI 4,>0008 adjust table bottom ptr MOV 4,@>701E last free address Edited March 24, 2022 by senior_falcon 2 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 24, 2022 Author Share Posted March 24, 2022 I should add that E/A BASIC gives an "ILLEGAL TAG" error message when trying to load SPEAK. 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted March 24, 2022 Share Posted March 24, 2022 Could be a timing issue: [2888] *********************************************************** [2889] * SPEAK will actually speak the speech list. It tests the [2890] * timing byte to see if it is an >FF. If it is, then the [2891] * data following it points to a direct speech data string [2892] * in VDP. If it is not, then the data following it points [2893] * to a PHROM speech data list. In the first case, this [2894] * routine will issue a speak external command to the PHROM [2895] * and then feed bytes out to the PHROM as it requests them. [2896] * In the second case, the address will be loaded out to the [2897] * PHROM, and then a speak command will be issued. [2898] *********************************************************** [2899] B24C 06,B5,D1 SPEAK CALL SETRW Set read/write address [2900] B24F C9,00,02 GB1CE DCHE @PTLBSL,@PTFBSL More speech list to go [2901] B252 72,D9 BS GB258 [2902] B254 06,B5,C6 CALL WAIT Yes, wait until previous [2903] * speech is though [2904] B257 D6,B0,00 CEQ >FF,V*PTFBSL External speech data B25A FF [2905] B25B 72,7F BS GB1FE [2906] B25D BC,79,B0 ST V*PTFBSL,@TIMER No, load timer B260 00 [2907] B261 82,79 NEG @TIMER and neg it to correct [2908] B263 BD,12,E0 DST V@1(@PTFBSL),@PTFBPH Put addr into PTFBPH B266 01,00 [2909] B268 A3,00,00 DADD 3,@PTFBSL and skip to next node B26B 03 [2910] B26C D2,79,00 LOOP1 CGE 0,@TIMER Wait for time delay [2911] B26F 52,6C BR LOOP1 [2912] B271 8E,12 CZ @PTFBPH If there is data [2913] B273 72,7D BS GB1FC [2914] B275 06,B5,6C CALL LOADAD Load the addr to PHROM 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0051 RXB 2022 [2915] B278 BE,C0,00 ST >50,@PAD(@WRITE) and issue speak command B27B 5A,50 [2916] B27D 52,D6 GB1FC BR CONTIN [2917] B27F 91,00 GB1FE DINC @PTFBSL Speak external, skip over >FF [2918] B281 BD,5E,B0 DST V*PTFBSL,@PTCBED Set up pointer to 1st byte B284 00 [2919] B285 BD,5E,E0 DST V@4(@PTCBED),@PTCBED in external speech data B288 04,5E [2920] B28A 95,00 DINCT @PTFBSL Skip addr bytes [2921] B28C BC,62,EF ST V@-1(@PTCBED),@LENWST Get Len of whole string B28F FF,FF,5E [2922] B292 A6,62,03 DIRSPH SUB 3,@LENWST Minus 3 bytes overhead [2923] * All external speech strings start with a >60 [2924] B295 D6,B0,5E CEQ >60,V*PTCBED Bad speech string B298 60 [2925] B299 4D,99 BR ERRBV [2926] B29B 06,B5,C6 CALL WAIT Wait for go ahead [2927] B29E 95,5E DINCT @PTCBED Skip spk ext & 1st byte len [2928] B2A0 BC,60,B0 ST V*PTCBED,@LENCST Get len of current string B2A3 5E [2929] B2A4 91,5E DINC @PTCBED Skip len byte to 1st real byt [2930] B2A6 BE,56,10 ST 16,@TEMP2 Do 1st 16 bytes (fill buff) [2931] B2A9 BE,C0,00 ST >60,@PAD(@WRITE) Start Speak External B2AC 5A,60 [2932] B2AE BC,C0,00 LOOPR ST V*PTCBED,@PAD(@WRITE) Write byte to PHROM B2B1 5A,B0,5E [2933] B2B4 91,5E DINC @PTCBED Go to next byte [2934] B2B6 92,62 DEC @LENWST 1 less char in whole string [2935] B2B8 72,D6 BS CONTIN Finished whole string? [2936] B2BA 92,60 DEC @LENCST 1 less char in curr string [2937] B2BC 72,92 BS DIRSPH Finished current string? [2938] B2BE 92,56 DEC @TEMP2 1 less char in this loop [2939] B2C0 52,AE BR LOOPR Not finished curr loop yet? [2940] B2C2 BC,69,C0 GB241 ST @PAD(@READ),@SPKSTS Read status from PHROM B2C5 00,58 [2941] [2942] * If the next statement is true, it means that speak was [2943] * probably interupted and that it is shot at this point. [2944] * Therefore, we are going to quit now. [2945] B2C7 DA,69,80 CLOG >80,@SPKSTS [2946] B2CA 72,D6 BS CONTIN [2947] B2CC DA,69,40 CLOG >40,@SPKSTS Loop till buff below half [2948] B2CF 72,C2 BS GB241 [2949] B2D1 BE,56,08 ST 8,@TEMP2 Put 8 more bytes to PHROM [2950] B2D4 52,AE BR LOOPR and go do these [2951] B2D6 05,B2,4F CONTIN B GB1CE We've said it all!! [2952] * Now pop all entries off stack that we put on! [2953] B2D9 0F,78 GB258 XML VPOP Free up a temporary string [2954] B2DB D5,6E,4C DCEQ @FAC2,@VSPTR [2955] B2DE 52,D9 BR GB258 [2956] B2E0 4A,C0 BR LNKRTN Quote Link to comment Share on other sites More sharing options...
RXB Posted March 24, 2022 Share Posted March 24, 2022 CALL SAY and CALL SPGET along with CALL SOUND are the very largest GPL subroutines in XB. And none of any of them are Assembly so cannot say why but it is a fact. Never spent any time with GPL of the Mini Memory as Basic sucks compared to XB. The debugger in Mini Memory is great but nothing else ever appealed to me. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 24, 2022 Author Share Posted March 24, 2022 This bug has nothing to do with speech or GPL. The problem is simple: CALL INIT then CALL LOAD("DSK3.SPEAK") is supposed to load an assembly object code file. This works in TI Extended BASIC (the loader is written in GPL) Gives a "ILLEGAL TAG" error message in E/A BASIC (loader written in assembly) Goes into a black hole in cyberspace in MiniMemory BASIC (loader written in assembly, but obviously not identical to the E/A loader) What is it about the file that causes it to not work in E/A or MiniMem BASIC? Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 24, 2022 Author Share Posted March 24, 2022 On page 415 of the E/A manual is a list of the object tags in E/A and XB The only one that matches this behavior is this: Tag M Data/Common Seg. ignored in XB Issues error in E/A I'm guessing that is the problem and will experiment some more tonight. Looks like the fix is simple - just amend the manual to reflect this behavior. 4 Quote Link to comment Share on other sites More sharing options...
pixelpedant Posted March 24, 2022 Share Posted March 24, 2022 This is a rather cool finding even if it doesn't bear further fruit! But I'm certainly hopeful that it does bear further fruit, and the utility and compatibility of the Text-to-Speech routines in a BASIC context can be enhanced. Quote Link to comment Share on other sites More sharing options...
RXB Posted March 24, 2022 Share Posted March 24, 2022 I have thought about adding Text to Speech into XB ROMS would name it CALL SPEECH("String to speak") Of course it would require a buffer to be set up as a temporary file for XB to access and I could place it next to XB VDP stack so less likely to be involved in Garbage Collection routine and could be closed with CALLL SPEECH(#?#) Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 25, 2022 Author Share Posted March 25, 2022 Using a hex editor I could look at the first line of SPEAK. Sure enough, the 14th byte is a M which is supposed to stand for Data/common seg. and that is ignored by XB and issues an error in the E/A loader. The tag for Program ID is an I, and it should be ignored by both the XB and E/A loaders. I was hoping that changing the M to an I would make the file loadable by both XB and E/A, and hopefully MiniMemory. But it just gives an "unrecognized character" message. Any ideas on how to change the first line so it will load all three ways? In the disassembly of the MiniMemory ROM are these lines with the note that tags K to P branch to crazy locations! A65F8 BYTE >2D tag 0 BYTE >5D,>5C tag 1+2 BYTE >6E,>6F tag 3+4 BYTE >A3,>A4 tag 5+6 BYTE >60,>04 tag 7+8 BYTE >67,>66 tag 9+A BYTE >6A,>69 tag B+C BYTE >CF,>CF tag D+E error 10 BYTE >03 tag F BYTE >CF,>CF tag G+H error 10 BYTE >52 tag I skip 8 chars BYTE >00 tag J tag in data word * tags K to P branch to crazy locations! * Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 25, 2022 Share Posted March 25, 2022 Maybe the trick is not to patch it, but just resave it? According to my notes, SPEAK loads at >24F4 (reserving workspace there), and are >06D4 bytes (ending at >2BC7). Classic99 can save memory as EA#3 uncompressed, which XB loaders are supposed to be too, but in this case only the absolute data tags will be used. This does have the small problem that no memory will be reserved/allocated/marked used when loading... but it's probably easier to patch this one with the much simpler header. This also DOES NOT set up the Ref/Def table, since it's just a memory dump. Guess it depends on the use whether it's useful. In fact, to keep it simple, I saved SPEAK, XLAT and SETUP all in one file here: SPEAK - 24F4 to 2BC7 XLAT - 2BC8 to 33B1 SETUP - 33B2 to 3683 Then I saved off the database - this means that SETUP doesn't need to work or be called. I manually added the ref/defs to the end. XLAT -> 2BE8 SPEAK -> 2514 There is still the problem of the XB utils... my notes say that these are used: SPEAK: ERR (BLWP @>2034) - 25C8 STRREF (BLWP @>2014) - 253E NUMREF (BLWP @>200C) (twice) - 2556 and 256A XMLLNK (BLWP @>2018 - DATA >12B8) (twice) - 255A and 256E - my notes say >1200 is float to int and I wasn't sure about the B8 part, but it clearly wants float to int. XLAT: ERR (BLWP @>2034) (twice) - 2BFC and 2C3C STRREF (BLWP @>2014) - 2C16 STRASG (BLWP @>2010) - 2C56 So, that's only 10 points that need to be patched up. You could hard-code the changes for the MiniMem or E/A entry points, or change them to proper refs. Might work? Maybe I'm off base, I dunno. Fun to look at for a moment. SPEAKV2.zip 3 Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 25, 2022 Share Posted March 25, 2022 Here's my partial disassembly of the XB speech code, in case it's helpful. I see now too that you're in XB anyway, so maybe the XB utilities are present and should work out... SpeechCart.zip 1 1 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted March 25, 2022 Share Posted March 25, 2022 To test that SPEAK, XLAT, and ALPHON, were truly relocatable, I readjusted the FIRST/LAST free memory pointers at >2002, >2004, before loading them individually. They seemed to run fine from >D000+. P.S. NUMREF, seems to be misreferenced on E/A, page 416, >2000 is the XML vector to XB's, DEF TABLE, parser. I believe that NUMREF should be called from >200C. 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 25, 2022 Share Posted March 25, 2022 2 hours ago, HOME AUTOMATION said: P.S. NUMREF, seems to be misreferenced on E/A, page 416, >2000 is the XML vector to XB's, DEF TABLE, parser. I believe that NUMREF should be called from >200C. Yes. That is, indeed, an error in the E/A manual. >200C it is. ...lee 3 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 25, 2022 Share Posted March 25, 2022 My first guess from the assembly was that R4 and R6 were garbage. Also XB doesn’t use REF so this should never come up. If R4 is supposed to be the last free address (that is, start of the ref table) it is garbage >0180. R6 is supposed to point to the REF to be removed but it’s 0. So I guess that that M tag branches to a weird location and R4 and 6 are not valid so it fails. I would remove the M tag by deleting the M and the 4 hex chars after. At the end of the line, you may have to fix up the 7 tag, checksum, by changing it to 8, ignore checksum. (7 to 8 is what you do when you edit any line.) M is not supposed to be in 4A object files! You can’t assemble a PSEG or CSEG directive in ASSM1. You need an assembler like SDSMAC on a 990/12 (or /10 with memory mapping upgrade). Curious, what is the last line of the object file? It should tell the name of the assembler! I think E/A files say 99/4 A/S or something. Many speech files that I have looked at say SDSMAC, indicating they were produced on a 990. In 990 o/s DX10 or DNOS, a program gets 64K of its own address space. This is divided into 3 segments , which can map anywhere in 1 Meg system RAM. The LMF instruction sets up the address and size of the 3 segments. One way to use 3 segments is to have: 1. PSEG: Program segment (shared if possible, plus it hangs around in case you run the program again.) (PSEG) Marked read-only but executable. optionally? loadable from object file: CSEG: Common program segment. Relocatable code just like PSEG, but identified by a different label and I think linkable separately from outside. 2. DSEG: Data constants, text, etc. (Not sure if this intended to be read-only? but no-execute. I'm not sure if this is shared.) 3. User RAM. Stack, heap, and so on. The program might make a SVC call (defined with DXOP as XOP 15) that asks the OS to extend this RAM boundary (until the 64K is full.) Obviously, allows read and write by the program. I’ve never programmed in that environment, so my book-learning could be wrong. Anyhow that’s where I believe the M would come from. I guess it’s really a no-op on the 4A because code and data are treated the same. Conceivably, a PSEG might go in a separate address space altogether—Harvard architecture—from which instructions are always fetched, but not data. So PSEG could be 64K, and CSEG + user RAM could have 64K. The 99000 facilitated this. The 9900 is not Harvard— it’s plain old Von Neumann or MIT architecture, where code and data are treated the same. (You can have self-modifying code or use code as data.. both illegal at Harvard.) 2 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 26, 2022 Author Share Posted March 26, 2022 (edited) 10 hours ago, FarmerPotato said: I would remove the M tag by deleting the M and the 4 hex chars after. At the end of the line, you may have to fix up the 7 tag, checksum, by changing it to 8, ignore checksum. (7 to 8 is what you do when you edit any line.) M is not supposed to be in 4A object files! You can’t assemble a PSEG or CSEG directive in ASSM1. Thanks for the advice. I tried that a couple different ways - by deleting those 5 characters and by spacing over the characters. Changed 7 to 8 and get I/O error 2 when I try to load. This was in standard XB, so I didn't even try it in MiniMemory or XB 2.9 G.E.M. It is odd that those unuseable directives are even mentioned! The assembler is not identified as far as I can tell. You can look at SPEAK with a hex editor if you are curious. Edited March 26, 2022 by senior_falcon 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 26, 2022 Share Posted March 26, 2022 13 hours ago, Lee Stewart said: Yes. That is, indeed, an error in the E/A manual. >200C it is. ...lee That's what I wrote 1 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 27, 2022 Share Posted March 27, 2022 23 hours ago, senior_falcon said: Thanks for the advice. I tried that a couple different ways - by deleting those 5 characters and by spacing over the characters. Changed 7 to 8 and get I/O error 2 when I try to load. This was in standard XB, so I didn't even try it in MiniMemory or XB 2.9 G.E.M. It is odd that those unuseable directives are even mentioned! The assembler is not identified as far as I can tell. You can look at SPEAK with a hex editor if you are curious. I found the syntax for M in the TXDS Link Editor Manual. TXDS is an operating system for 990/4 or /10 but SDSLNK was probably common to others. M has 2 arguments. TAG FIELD1 FIELD2 FIELD3 0 PSEG length Program ID (8) - M DSEG length $DATA 0000 M Blank CSEG length $BLANK 0001 M CSEG Length Common Name(6) Common # M CBSEG Length $CBSEG CBSEG# Here is the weird tag in the SPEAK object: M0000$DATA 0000 Did you remove all of that, up to the 7 (checksum tag)? I guess the 7F954F could be replaced with just F (the end of record tag) The last line, after the DEF table, names the TI Link Editor SDSLNK: SPKL0057 02/24/82 10:34:27 SDSLNK 3.4.0 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 27, 2022 Author Share Posted March 27, 2022 8 hours ago, FarmerPotato said: Did you remove all of that, up to the 7 (checksum tag)? I guess the 7F954F could be replaced with just F (the end of record tag) Both ways did the trick. I removed up the the checksum tag and changed that to 8 and it works fine. Then I tried taking out everything up to the F and that also worked. Thank you very much! 3 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted March 27, 2022 Share Posted March 27, 2022 Over the last couple days, I've made several varied attempts at this myself. Always with similar results... I'm editing at the .DSK image level. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted March 27, 2022 Author Share Posted March 27, 2022 I think my post was not clear enough. Replace the M with F, then replace the rest of the characters with spaces up to the final F. That should do it. Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted March 27, 2022 Share Posted March 27, 2022 That should work… The F means end of line. You can delete from M all the way to the end, and have one Final F. As if the M was never there. Also the 0000 after the M means empty… so I guess SDSLNK is pedantic. I love finding out these things. It’s like etymology or history, as our 4A world came out of 990 land, a bigger, older place. I don’t think any other home computer got a heritage like that? The PC purposely broke away from all prior IBM hardware and software. Imagine if DEC had made a Rainbow home computer? (not just their 8088 DEC Rainbow 100 PC). I’m imagining a LSI-11 CPU in a console. A home version of a DEC PDP-11, much like we got a home 9900, a minicomputer on a chip. That LSI-11 would have been a fun machine if it’s ecosystem had a derivative of one of the smaller PDP-11 operating systems. All those LISP programmers taking time off to write games for it! My brief experience programming the PDP-11 was a joy even though the tools were primitive. (ED—Line by line editor—AS the assembler—that was it.) I edited on the 4A, then uploaded PDP-11 assembly source using Telco into ED!) The PDP-11 (hence LSI-11) machine language, being 16-bit, was sweet and a lot like 9900. I don’t know what O/S it was (rebranded by Kaman Sciences as KIS) maybe one of the small multi terminal ones like RSX-11? It had system calls for everything, which I saw similar in CP/M and MS-DOS. I learned its disk file structures: they were multi level B trees of sector numbers. So a sector could be deleted or inserted in the middle, or file sorted! I disassembled the serial interrupt handler (a ring buffer.) If DEC had made a LSI-11 home computer, I would have been doing that in front of a TV. Don’t mention VMS. It could have run Unix! (It’s source for Unix v.6 you can read on the web.) OK digression over. this is a text-to-speech thread. 3 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.