GroovyBee Posted December 10, 2016 Share Posted December 10, 2016 Find attached a way of handling an array of strings that are each of arbitrary length. ArrayOfStrings.bas The code produces the following output :- @nanochess: Feel free to add it to the next release of IntyBASIC. Comments/suggestions? 3 Quote Link to comment Share on other sites More sharing options...
First Spear Posted December 14, 2016 Share Posted December 14, 2016 Great stuff! Now to take it to the next level, I have about 90 strings. I was going to use macro features of my text editor to wrap everything as you did in the sample, is that the most sensible approach? What I want to do is take a set of strings and scroll them horizontally "up" the screen. I originally thought that I could use an array of strings, but that datatype is not supported I now understand. Here is the look I am trying to go for, except instead of 3 elements, I will have 90 so I need to keep track of the set position so I can hide and show in the visible window. ' An array of pointers to strings. ArrayOfStrings: data varptr Msg1(0) data varptr Msg2(0) data varptr Msg3(0) ' String #1 Msg1: asm DECLE @@Msg1End-@@Msg1Start asm @@Msg1Start: data "Hello" asm @@Msg1End: ' String #2 Msg2: asm DECLE @@Msg2End-@@Msg2Start asm @@Msg2Start: data "Intellivision" asm @@Msg2End: ' String #3 Msg3: asm DECLE @@Msg3End-@@Msg3Start asm @@Msg3Start: data "Programmers" asm @@Msg3End: Thanks for all ideas! Find attached a way of handling an array of strings that are each of arbitrary length.@nanochess: Feel free to add it to the next release of IntyBASIC.Comments/suggestions? 1 Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted December 14, 2016 Author Share Posted December 14, 2016 Great stuff! No problem! I was going to use macro features of my text editor to wrap everything as you did in the sample, is that the most sensible approach? I used the macro features of AS1600 instead , to make the IntyBASIC code less "polluted": ArrayOfStrings.bas 2 Quote Link to comment Share on other sites More sharing options...
catsfolly Posted December 15, 2016 Share Posted December 15, 2016 If you have a bunch of strings and you want to select and print them randomly, then an array of strings is the perfect tool. But, if you just want to print a list of strings sequentially to the screen, it seems like overkill! I would suggest: 1. Put the strings in one big data list, 2. Use the scroll command to move the screen up. 3. Print the next line at the bottom of the screen. 4. Clear the rest of the bottom line if necessary. 5. Terminate the list with a zero (since the string length would normally not be zero). Done! Here is a quick hacked example: < click to animate. And the code: zz.bas Catsfolly 1 Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted December 15, 2016 Author Share Posted December 15, 2016 5. Terminate the list with a zero (since the string length would normally not be zero). This may or may not work depending on how the strings are stored. If you put the strings directly into IntyBASIC data statements then the compiler will automatically subtract 32 from each ASCII value in the string, before putting the value in ROM. Thus a space (" ") will be encoded as a zero and cause early termination. Your version of the TEXT macro uses the AS1600 STRING directive which does no such preprocessing, so in that case, zero is a valid terminator. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted December 15, 2016 Author Share Posted December 15, 2016 Solved the problem just using IntyBASIC commands :- ArrayOfStrings.bas 3 Quote Link to comment Share on other sites More sharing options...
+nanochess Posted December 15, 2016 Share Posted December 15, 2016 Solved the problem just using IntyBASIC commands :- ArrayOfStrings.bas Pretty elegant 1 Quote Link to comment Share on other sites More sharing options...
catsfolly Posted December 16, 2016 Share Posted December 16, 2016 This may or may not work depending on how the strings are stored. If you put the strings directly into IntyBASIC data statements then the compiler will automatically subtract 32 from each ASCII value in the string, before putting the value in ROM. Thus a space (" ") will be encoded as a zero and cause early termination. Your version of the TEXT macro uses the AS1600 STRING directive which does no such preprocessing, so in that case, zero is a valid terminator. No, I'm not checking each individual character of a string for a zero terminator, only the first element, which is the string length. When I encounter a string of zero length in my list, I assume the list is finished. 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 16, 2016 Share Posted December 16, 2016 No, I'm not checking each individual character of a string for a zero terminator, only the first element, which is the string length. When I encounter a string of zero length in my list, I assume the list is finished. That's how I handle strings as well. The length is on the first byte of the string array, and it must not be zero. Therefore a zero word will mark the end of the strings table. -dZ. 1 Quote Link to comment Share on other sites More sharing options...
First Spear Posted December 16, 2016 Share Posted December 16, 2016 (edited) Is it possible to only scroll the right half of the screen with this technique? I want to keep columns 0-10 static because I have another image to show there. The docs and contrib\scroll.bas both seem to indicate that scrolling is a whole screen affair (I can't think of an Inty game that doesn't scroll the whole screen actually). Thanks. If you have a bun[snip] Catsfolly Edited December 16, 2016 by First Spear 1 Quote Link to comment Share on other sites More sharing options...
carlsson Posted December 16, 2016 Share Posted December 16, 2016 As far as I understand, the STIC registers are updated during VBL so when it comes to scrolling it is all or nothing. Thus some people have discussed methods to "counter-scroll" items that are supposed to be static on screen, but doing that for 10 columns times 12 rows may be very cumbersome, if possible at all. 1 Quote Link to comment Share on other sites More sharing options...
catsfolly Posted December 16, 2016 Share Posted December 16, 2016 Is it possible to only scroll the right half of the screen with this technique? I want to keep columns 0-10 static because I have another image to show there. The docs and contrib\scroll.bas both seem to indicate that scrolling is a whole screen affair (I can't think of an Inty game that doesn't scroll the whole screen actually). Thanks. This example uses the "scroll" command to move the text up on the screen. The scroll command operates on the whole screen. To scroll only the right half of the screen, you would have to write a routine to move the text up on the screen that operates only on the right half of the screen. This could be written in IntyBasic, but without trying it I don't know if it would be fast enough - maybe an assembly routine would be necessary. I have to get ready for work, so I can't try it now... We are talked about "crude scrolling" in this case (scrolling 8 bits at a time, like the example code). "Smooth scrolling" (1 bit at a time) can only happen on the whole screen. If you can live with "crude scrolling" (on the Colecovision it's the only kind of scrolling they have), then there is no reason not to have independent scrolling windows on the Intellivision... Catsfolly 2 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 17, 2016 Share Posted December 17, 2016 Solved the problem just using IntyBASIC commands :- ArrayOfStrings.bas But that still packs the strings one byte per DECLE. I think we can get away with packing them two per decle using additional macros. The "Print" routine would have to be smart enough to unpack during output. I have macros and routines for this in Assembly. Would they be worth translating/wrapping to work with IntyBASIC? -dZ. Quote Link to comment Share on other sites More sharing options...
mmarrero Posted December 17, 2016 Share Posted December 17, 2016 But that still packs the strings one byte per DECLE. I think we can get away with packing them two per decle using additional macros. The "Print" routine would have to be smart enough to unpack during output. I have macros and routines for this in Assembly. Would they be worth translating/wrapping to work with IntyBASIC? -dZ. Hi dZ. I hacked modified GroovyBee's code to print packed strings, also in 100% IntyBasic. It's specifically for packed strings, I can't think of an easy way to tell string types apart. Maybe by also storing sizeof(), or, terminating with $FF, and check if LEN()/2 points to it. include "constants.bas" '---- string is packed in 8-bit pairs. Data len(aString) is the string length, not size in memory def fn TEXTPACKED(aString) = data len(aString): data packed aString '---- packed strings ------ ' Print the 1st packed string. index=0 ' The index of the packed string we are interested in. #where=SCREENADDR(0,4) ' Where the packed string is going to on the screen. colour=CS_WHITE ' The string colour (Note: Only first 8 colours are allowed). gosub PrintStringPacked ' Print the packed string on the screen. ' Print the 2nd packed string. index=1 #where=SCREENADDR(0,5) colour=CS_TAN gosub PrintStringPacked ' Print the 3rd packed string. index=2 #where=SCREENADDR(0,6) colour=CS_BLUE gosub PrintStringPacked loop: wait goto loop REM ------------------------------------------------------------------------- PrintStringPacked: procedure ' Get the start address in ROM of the string we need. #addr=ArrayOfStringsPacked(index) ' Get the size of the packed string length=peek(#addr) #addr=#addr+1 ' Print the packed string on screen. WHILE length<>0 #data=peek(#addr) ' Get 16-bit value poke #where,(#data/256)*8+colour ' Write 1st 8-bit value to BACKTAB. (MSB) #where=#where+1 ' Move to the next position on screen. length=length-1 IF length=0 THEN EXIT WHILE ' Finished? Exit.. poke #where,(#data AND $FF)*8+colour ' Write 2nd 8-bit value (LSB) #where=#where+1 ' Move to the next position on screen. #addr=#addr+1 ' Move to the next character location in ROM. length=length-1 WEND end REM ------------------------------------------------------------------------- REM PrintStringPacked - END ' An array of pointers to packed strings. ArrayOfStringsPacked: data varptr Msg1P(0) data varptr Msg2P(0) data varptr Msg3P(0) ' String #1 Msg1P: TEXTPACKED("Hello Again") ' String #2 Msg2P: TEXTPACKED("Intellivision") ' String #3 Msg3P: TEXTPACKED("Programmers!") 4 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 17, 2016 Share Posted December 17, 2016 Hi dZ. I hacked modified GroovyBee's code to print packed strings, also in 100% IntyBasic. It's specifically for packed strings, I can't think of an easy way to tell string types apart. Why would you need to? Assume that calling PrintStringPacked() will be called with a packed string, and Bob's your uncle. Unless you mean how to know when a string ends and another one begins? Storing the length on the first byte allows you to know how long your loop is. The string index table will take care of the beginning pointer for each string. -dZ. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted December 17, 2016 Author Share Posted December 17, 2016 Is it possible to only scroll the right half of the screen with this technique? I want to keep columns 0-10 static because I have another image to show there. If the left side image is reasonably simple and uses MOBs for colour highlights then you can prepare vertically pre-shifted graphics in GRAM and use those while scrolling the whole screen up pixel by pixel. Quote Link to comment Share on other sites More sharing options...
mmarrero Posted December 18, 2016 Share Posted December 18, 2016 Why would you need to? Assume that calling PrintStringPacked() will be called with a packed string, and Bob's your uncle. Unless you mean how to know when a string ends and another one begins? Storing the length on the first byte allows you to know how long your loop is. The string index table will take care of the beginning pointer for each string. -dZ. Oh, I meant just having one PrintString function that prints them all. (both packed and unpacked). I already used PrintStringPacked() with the wrong non-packed strings... Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 18, 2016 Share Posted December 18, 2016 Oh, I meant just having one PrintString function that prints them all. (both packed and unpacked). I already used PrintStringPacked() with the wrong non-packed strings... Ah. Maybe that wouldn't be practical, unless you reserve a high-order bit of the first byte to mark the format, or something like that. You could also store meta-data in the string index table, along with the starting pointer. -dZ. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted December 18, 2016 Author Share Posted December 18, 2016 By making the length negative in the def fn for packed strings, both kinds of stings can easily be handled by one procedure, as follows: ArrayOfStrings.bas 4 Quote Link to comment Share on other sites More sharing options...
catsfolly Posted December 19, 2016 Share Posted December 19, 2016 The sound of half a screen scrolling: Here is a hack of my hack to just scroll half of the screen. (Note: I have not updated my strings yet to GroovyBee's latest format yet.) <- click to animate Source code: zzz.bas Catsfolly 4 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 19, 2016 Share Posted December 19, 2016 The sound of half a screen scrolling: Here is a hack of my hack to just scroll half of the screen. (Note: I have not updated my strings yet to GroovyBee's latest format yet.) mvi_0080.gif <- click to animate Source code: zzz.bas Catsfolly Nice. Now try it with smooth scrolling, by counter-scrolling the "nice picture." 1 Quote Link to comment Share on other sites More sharing options...
catsfolly Posted December 19, 2016 Share Posted December 19, 2016 Mr. Spear never asked for smooth scrolling. Depending on the picture, it may or may not be possible... 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 19, 2016 Share Posted December 19, 2016 Mr. Spear never asked for smooth scrolling. Depending on the picture, it may or may not be possible... I know he didn't, I did. Quote Link to comment Share on other sites More sharing options...
First Spear Posted January 22, 2017 Share Posted January 22, 2017 I am playing with some the variables, trying to define the beginning and ending column for the string. All of my strings are 8 characters in length exactly. I do not understand the relationship between the #where variable and the BACKTAB_ADDR. Can you help me get a clue? Thanks. printloop: wait #addrs = BACKTAB_ADDR + 10 for c = 0 to 10 poke #addrs , peek(#addrs + 20) poke #addrs+1 , peek(#addrs + 21) poke #addrs+2 , peek(#addrs + 22) poke #addrs+3 , peek(#addrs + 23) poke #addrs+4 , peek(#addrs + 24) poke #addrs+5 , peek(#addrs + 25) poke #addrs+6 , peek(#addrs + 26) poke #addrs+7 , peek(#addrs + 27) poke #addrs+8 , peek(#addrs + 28) poke #addrs+9 , peek(#addrs + 29) #addrs = #addrs + 20 next c length = Msgs(#string_index) if length = 0 then goto restart #string_index = #string_index + 1 #where = BACKTAB_ADDR + (11 * 20) + 10 for c=1 to length #data=((Msgs(#string_index) - 32) * 8 )+colour ' Get the character poke #where,#data #string_index = #string_index+1 #where = #where+1 next c rem clear the rest of the line zfill: if (c < 21) then poke #where,0 : c = c + 1 : #where = #where + 1 : goto zfill for c = 0 to 50 wait next c goto printloop The sound of half a screen scro[snip] 1 Quote Link to comment Share on other sites More sharing options...
catsfolly Posted January 23, 2017 Share Posted January 23, 2017 (edited) I am playing with some the variables, trying to define the beginning and ending column for the string. All of my strings are 8 characters in length exactly. I do not understand the relationship between the #where variable and the BACKTAB_ADDR. Can you help me get a clue? Thanks. printloop: wait #addrs = BACKTAB_ADDR + 10 for c = 0 to 10 poke #addrs , peek(#addrs + 20) poke #addrs+1 , peek(#addrs + 21) poke #addrs+2 , peek(#addrs + 22) poke #addrs+3 , peek(#addrs + 23) poke #addrs+4 , peek(#addrs + 24) poke #addrs+5 , peek(#addrs + 25) poke #addrs+6 , peek(#addrs + 26) poke #addrs+7 , peek(#addrs + 27) poke #addrs+8 , peek(#addrs + 28) poke #addrs+9 , peek(#addrs + 29) #addrs = #addrs + 20 next c length = Msgs(#string_index) if length = 0 then goto restart #string_index = #string_index + 1 #where = BACKTAB_ADDR + (11 * 20) + 10 for c=1 to length #data=((Msgs(#string_index) - 32) * 8 )+colour ' Get the character poke #where,#data #string_index = #string_index+1 #where = #where+1 next c rem clear the rest of the line zfill: if (c < 21) then poke #where,0 : c = c + 1 : #where = #where + 1 : goto zfill for c = 0 to 50 wait next c goto printloop BACKTAB_ADDR is the address of the data that will appear at the upper left hand corner of the tv screen. #where = BACKTAB_ADDR would point to the upper left hand corner data. Since there are 20 characters across on the Intellivision display, the next row of characters would start at: #where = BACKTAB_ADDR + 20 The next row of characters would start at: #where = BACKTAB_ADDR + 40 So, in general, the address of the first character in a row would be (assuming that the top row is row 0): #where = BACKTAB_ADDR + (row_number * 20) In the code above we have the line: #where = BACKTAB_ADDR + (11 * 20) + 10 This points to the 11th row, starting at the 10th character. This is at the very end of the screen memory, so if your code writes more than 10 characters starting at this position (which it appears to do) , it will corrupt memory beyond the end of the backtab memory, which could cause the program to crash. Does this help? Catsfolly P.S. Constants.bas has a nice macro that does the calculations automatically: #where = screenadrs(10,11) The first number is the column and the second number is the row.. Edited January 23, 2017 by catsfolly 1 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.