Jump to content

pixelpedant

Members
  • Posts

    1,121
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by pixelpedant

  1. Well that does make a certain amount of sense, since you're already talking about using far more data than a TI BASIC program may contain. In that your limit on the size of a TI BASIC program is ~12KB, and you're talking about storing DATA lines within the program containing 100 x 72 values per level x 3 bytes per numeric value minimum (unquoted string token, length byte, 1 numeric character) = 21.6KB in numeric DATA alone. So if those are your criteria and compiling is the goal, I'd just write for the compiler, and accept that what you're writing is not a functional TI BASIC program and cannot be stored in the Program format, but can nonetheless (potentially) be used to produce a working compiled program written using TI-BASIC-like structures.
  2. Certainly, the presence of CALL CHAR and custom character patterns makes all the difference in the world, as far as allowing developing for the device to be interesting in its own right (rather than just functional as a destination for ports of traditional text-based games). Plus, on top of the 31 character screen, you've got the six indicator arrows along the bottom of the display which can be toggled on and off. And as well, the various status indicators (like "Rad") to do with as you will. Finally, you've got the beeper, if you want to use that. So there's a fair amount to work with there that isn't just an alphanumeric display.
  3. Why not just read this data from disk? There you can read whatever record you want.
  4. No, you cannot in any direct way conditionally designate the destination of a RESTORE. Under the hood (i.e., in the tokenised BASIC), as with GOTO or GOSUB, RESTORE (when used with DATA statements) accepts a single parameter, which is a word value representing the line from which (or subsequent to which) DATA shall be thereafter read. It is not an evaluated expression. It is an immutable constant. The only ways I am aware of by which to determine the location of a READ based on a variable value N is 1) RESTORE to a fixed point, then loop over READs of consecutive values until you have read the Nth value. 2) Use ON N GOTO or ON N GOSUB to pass control to the Nth RESTORE statement in a series thereof, specifying the desired lines for respective values. It must be noted that RESTOREing excessively is *very* undesirable, as it is very slow. So even were one able to RESTORE more flexibly, you probably wouldn't want to. You want to READ consecutive values if at all possible, as this is much faster.
  5. As is often the case with me, since I'd already created a video titled "My Top TI-99 Extended BASIC Tips and Tricks" I suppose I can refer you to that. You may also want to consult the Millers Graphics Smart Programming Guide for Sprites.
  6. The XB Game Developer's Kit is the solution you're looking for, and provides excellent documentation, explaining it's use in detail and comprehensively. If you're looking for some demonstration and discussion:
  7. Yeah, my family picked up various Toys R Us TI stuff when they were clearing out their inventory on an "everything must go" basis, and that even included a Munch Man display cart with one of these tethers, which I still have somewhere.
  8. The TI CC-40 made its public debut at Winter CES, in January 1983. So happy 40th birthday, CC-40! In honour of its anniversary, I've done a video, to spread the word on the machine. Hopefully a few folks are introduced to it, who weren't before: The scope is limited, but I wanted to provide an accessible intro the machine and its use. I'll probably do more detailed and specific videos in the future. Wishlist items for the CC-40's anniversary year: - Progress on a screen mod/replacement solution, for the majority of units with bad screens. - Progress on a video interface (such as was planned). - A project on my part to develop an appealing CC-40 action game which really exploits CC-40 BASIC.
  9. One thing I find compelling about the CC-40's performance characteristics, vis-a-vis those of TI-99 BASIC, is that its much faster string operations mean that manipulating/generating/selecting character patterns in their hexadecimal string format is a more credible possibility. So for example, in the second program, all the 7 character patterns are generated via the value RPT$("1F",C)&"0E04". And in the first program, character 4 is animated using the value SEG$("040A1B0A15000A15040A1B0A15",(D-1)*16+1,16) Given you only have those 7 custom patterns, manipulating/generating character patterns on the fly makes a good deal of sense. Since you can't just write a big pile of patterns all at once and be done with it. And a lot of graphical updates or animations are going to have to be done with CALL CHAR, during program execution. But happily, the machine performs well enough in these regards to accommodate this.
  10. And here is another completely different one I just cooked up, but one I think I like a bit better, as it is a "natural" 10-liner. That is to say, no multi-statement lines. Just some very space-economic string/pattern manipulation. Demo 2 - Short Clip (edit).mp4 Stare directly into the CC-40 screen with this one, and you eventually start to see the Matrix. Or just the dot matrix. Possibly both? 10 FOR C=0 TO 6 20 CALL CHAR(C,RPT$("1F",C)&"0E04") 30 NEXT C 40 FOR C=6 TO -5 STEP -1 50 F$=F$&CHR$(ABS(C)) 60 NEXT C 70 FOR P=1 TO 12 80 DISPLAY AT(1),SEG$(RPT$(F$,4),P,31) 90 NEXT P 100 GOTO 70
  11. Finally, I couldn't help but look at this and see it as a "Ten Liner Competition" sort of program, so I crammed it into nine lines in this version, instead: 10 S$=RPT$(CHR$(32),11) 20 FOR X=1 TO 7:T$=T$&CHR$(VAL(SEG$("4001234",X,1))):NEXT X 30 CALL CHAR(0,"0E1F1B181B1F0E0000000E1F0E") 40 CALL CHAR(2,"1B1B1B1F1F0303000E1F1B1B1B1F0E") 50 CALL CHAR(5,"03060E1B0E060300180C0E1B0E0C18") 60 FOR D=1 TO 2:FOR L=1-(D=2)*11 TO 1-(D=1)*11 STEP (D=2)*2+1 70 CALL CHAR(4,SEG$("040A1B0A15000A15040A1B0A15",(D-1)*16+1,16) 80 DISPLAY AT(1),SEG$(S$&CHR$(D+4)&S$,L,12)&T$&SEG$(S$&CHR$(7-D)&S$,13-L,12) 90 NEXT P:NEXT D:GOTO 60 Seems like the CC-40 is the perfect "10 liner" type platform. Since typing long programs is pretty rough. But at the same time, as sold, entering and running BASIC programs is what the machine is for.
  12. Updated code (and clip). Because I felt it needed more space ships. Novice mistake. Committing code with insufficient space ships. But also, to increase concision.
  13. Here's a CC-40 demo I put together today, which isn't too much trouble to type in if you have to (only 19 lines, now), but has a pleasant result. Could be something to leave running on a display or demonstration unit. Note: If you should ever wish this demo (or any other) to run persistently for an arbitrarily long period (i.e., until manually interrupted) execute the command CALL POKE(2096,1) before running (or add it to the program), as this will disable auto-power-off until system restart. Demonstration Clip: Demo 1 v2 - 30s edit.mp4 30 S$=RPT$(CHR$(32),11) 40 FOR X=1 TO 7 50 T$=T$&CHR$(VAL(SEG$("4001234",X,1))) 60 NEXT X 70 CALL CHAR(0,"0E1F1B181B1F0E") !C 80 CALL CHAR(1,"00000E1F0E") !DASH 90 CALL CHAR(2,"1B1B1B1F1F0303") !4 100 CALL CHAR(3,"0E1F1B1B1B1F0E") !0 120 CALL CHAR(5,"03060E1B0E0603") !LEFT 130 CALL CHAR(6,"180C0E1B0E0C18") !RIGHT 150 FOR D=1 TO 2 160 FOR P=1 TO 12 170 L=ABS(P-13*(D-1)) 175 CALL CHAR(4,SEG$("040A1B0A15000A15040A1B0A15",(D-1)*16+1,16)) 180 DISPLAY AT(1),SEG$(S$&CHR$(D+4)&S$,L,12)&T$&SEG$(S$&CHR$(7-D)&S$,13-L,12) 190 NEXT P 200 NEXT D 210 GOTO 150 Edit: Version 5, I think? I keep on tweaking this. Yeesh.
  14. As ArcadeShopper has mentioned in his store thread, plenty of copies are now available in his store, should anyone want to order them in the future: https://www.arcadeshopper.com/wp/store/#!/Pixelpedant-Software/c/143941511 Which should be a lot better for US folks, in the long run.
  15. It's a long way away from any of that, yet. But thank you for the vote of confidence! I've been working on the underlying subroutines and dungeon map generation and whatnot for a couple months now. But I'd say it'll take several more to get it to a playable state. Hopefully Summer 2023 sort of thing.
  16. It's popular, anyway. That's the TI Artist convention. Which is the most prevalent image format for bitmap art, in the platform's library as a whole. With the two files containing palette and pattern data respectively, of course. Which can then be trivially loaded on original hardware or integrated into a project, since they just represent the contents of VDP in those respects.
  17. There is not, in general. It was a limited run of a custom cart based on a license of limited duration. It's possible someone will jump through the legal and technical hoops to license and build them again some day. But for now, it's a rarity which is almost never available for sale or trade (since most who have one aren't giving theirs up).
  18. Nice. The world needs more TI BASIC music demos! On a system where making actual games in the native BASIC was extremely difficult, graphical music demos were a natural genre for the platform, allowing for worthwhile programming experimentation by the average user with worthwhile results. So those are always appreciated.
  19. ON GOSUB is definitely worth mastering. For complex conditionals with many possible input values, it can produce structures which are both faster and more memory-economic than any equivalent set of IF conditionals. The main 'trick' to it is just understanding that TI BASIC numeric variables are always and only floats, and accordingly, ON GOSUB does not care if its argument is precisely "1" or "2" or "3" or what have you. It only cares that it is closer to "1" (or 2, or 3, and so on) than to any other integer. And this creates a great deal of flexibility, where arbitrary input values can be arithmetically strong-armed into sufficient proximity to these integers. So for example, an ON GOTO from the program I'm currently working on is the following: 7720 ON (B-169)*(B-169)/97 GOTO 7800,7600,7500,6800,7000,6600,6400,6300 The purpose of the equation (B-169)*(B-169)/97 being, to take values of B ranging from 176 to 197, and conflate certain ranges therein, such that ON GOTO sees this as a set of sequential input values ranging from 1 to 8 (with different outcomes for each). Though in practice, it is a set of input values consisting of successive ranges (and in some cases, individual values) from 176 to 197.
  20. Named subroutines aren't too bad from a performance standpoint, but I still more or less never use them, favouring GOSUBs and the extremely useful (and exceedingly fast) ON GOSUB, with both of those being exceedingly fast.
  21. Really, what you generally want to do is use CALL COINC(ALL,X) for your detection of a collision in the game loop (which is quite fast, in XB terms, as the VDP status register flags collisions inherently, but only by indicating that one has occurred). Then, only if necessary and unavoidable, test whether it is a specific collision (which will be significantly slower). Many of the best 80s era XB action games simply pursue a design which is wholly dependent on CALL COINC(ALL,X). Which is to say, only one category of collision may occur (e.g., player touches one of the things that will kill the player), and when a collision (any collision) occurs, its consequence is therefore assumed. And that tendency is just a consequence of testing for individual collisions being so much slower. Still, the method I'd mentioned, where CALL COINC(ALL,X) reports a collision (in general), and CALL DISTANCE or CALL POSITION is then (and only in that case) used to determine which of multiple possible collisions has occurred - that too can work acceptably. Another approach is to ditch automotion and just position your sprites with CALL SPRITE or CALL LOCATE (which are roughly equivalent in performance). Then, just determine collisions based on the already known coordinates of the sprites.
  22. I think that would make a great deal of sense. I'd considered writing a script to do this on my own behalf, actually, just because it would arguably result in more readable DATA statements. Since the character is ultimately not being used for the sake of the character itself in this case - it is being used for its numeric value. And so the Latin1 representation is ultimately meaningless, and a numeric representation, whether hex or decimal, would be more useful, in general.
  23. Well, CALL CHAR uses a numeric value as its character value, so this does originate as a character with a value greater than 127 in the DATA statements from which the value and ensuing pattern string is read, but ends up as a numeric value as far as CALL CHAR is concerned. In any case, all instances of characters greater than 127 (of which there are a great many) are now being successfully read from source and written to disk as desired, so I'm happy. XBAS99.PY is having no trouble with lines like the following, with all the string .encode and .decode methods just using Latin1 by default (and my editor set to Latin1 likewise): 15 DATA "¹RLCONSPIRING¹SMTO DESCEND¸h821928C492462831i9146482184126289¹RNTO CONQUER¹SOIN THE ENDÁBBA¾!9B^!6DZ¸jB2096A92AC219A44k4299244242249942" 16 DATA "¾ =;¼>7ÁBBH¾^8B^^5DZ]7=G>UÁNBAGBH¹KIHELL@S HEART°I°G°F°C³D¸l914E5045A20A7289m924C419205649229n894658A4251A6291oB25C42D684749A01" I shall perhaps have to try the IDEA option, in the future. This project is so built around interpreted data (housed in DATA statements, as above), that conventional code editing tools aren't as useful as they might be, but perhaps when next I have a saner project on my hands.
  24. Just wanted to say that XBAS99.py is making my life a whole lot easier, in my work on Hell's Heart (my next big TI BASIC project), right now. The tool is much appreciated, for its allowing me to get from plaintext source to tokenised code accessible to Classic99 in about 5 seconds flat. That having said, one issue I experienced is just that as written (at least on Windows and Python 3.11), it was necessary to change all the string conversion in XBAS99.PY to Latin1 rather than ASCII, as my program uses the full range of characters available to (i.e., which can be typed under) TI BASIC. Which is to say, 127-159 and 176-198 inclusive. Now, I grant the use of the latter is an oddball rarity (though extremely useful to me under present circumstances, as I need a fairly large number of tokens in a distinct range, separate from characters representing any printable graphic). However, the prior is probably a more typical necessity (given both Extended BASIC and Console BASIC can assign patterns to characters beyond the 7-bit ASCII range, and so read them in from DATA statements or DISPLAY AT the character sequence as a string literal). Anyway, for me, the fix was simply changing any use of the .encode or .decode methods to Latin1. i.e., s.encode(encoding='latin1') Thanks a lot for the tool. The best way to work on (while actively testing) a large TI BASIC or Extended BASIC program, it seems to me.
  25. ere's a very early teaser for the next TI BASIC cassette project I've been working on - Hell's Heart. The teaser just being the in-progress (and doubtless substantially to be revised) intro sequence (and in the background, pattern/palette loading process). This game intends to use more or less the entire range of available patterns (32-159), so pattern loading (and the intro which serves as a distraction, whilst this occurs) is even longer than was the case for Hell's Halls, at present. 2023-01-07 04-19-52.mp4 Project criteria are very similar to Hell's Halls: - TI Console BASIC - Type-in compatible: nothing which can't be typed directly into the TI BASIC interactive mode prompt. Characters 127-159 are used (for graphics) and 176-198 are used (for interpreter tokens), as these can all be typed with 99/4A-specific control/function key combinations. I was quite tickled by the fact that at least one person actually typed in and ran the type-in version of Hell's Halls. So I will definitely repeat that exercise. - Cassette compatible: nothing which can't be loaded from cassette in a single load (I considered loading patterns 128-159 via one program, then the remainder in the main program, immediately following on the same tape, but ultimately dismissed this as too cumbersome a loading process). Differences vis-a-vis Hell's Halls are: - My subprogram for drawing screen graphics (via HCHAR and VCHAR of course, as this is TI BASIC) has been hugely improved, to allow for detailed, compact, relatively fast (in TI BASIC terms) drawing of graphical components. The subprogram uses a (like practically everything here, 8-bit tokenised) data structure supporting repetition of HCHAR or VCHAR commands at specified offsets either horizontally or vertically. Such that, for example, all the graphics in the "table and candles" scene in the title sequence are drawn using the following data string: *MHq,4><CV4<C;)KL(KL>VK?VV which specifies (aside from Y,X,CHAR) a horizontal offset of three with four recurrences for all of 1) the candle flames, 2) candlesticks and 3) candle bases, and a vertical repetition of two for each candlestick. Repetition, Recurrence and Offset arguments are all optional, and so do not add to the length of the command in bytes for those commands not using them. The presence of each of these optional arguments is flagged in a preceding byte (of otherwise unrelated purpose), two earlier in the sequence, so that the subprogram knows whether to expect another argument or a new command. - My sound subprogram has been greatly improved, by virtue of arriving at a satisfactory method for approximating the sequence of frequencies of notes on the chromatic scale via multiplication/division/addition/subtraction alone (crucially, given the speed of exponentiation in TI BASIC). So in a music data string the character "C" now represents the note following "B" which represents the note after "A" etc. - Optional support for allophone speech via TE2 (with restrictions, as part of the allophone range and various allophone speech control characters cannot be typed in TI BASIC). We'll have to see how useful and desirable this ends up being. In any case, use of TE2 will be optional. But including speech has a significant memory cost (mainly due to the file buffer it uses, rather than the speech itself), so unless it's really adding something, it's arguably better to skip it. - Pattern loading is now handled by the interpreter like everything else, so patterns can be inserted into any DATA statement to be loaded, which makes it easier to seamlessly mix pattern loading and other events. Development is currently ongoing, mainly using Classic99 and Ralph Benzinger's xdt99 TI-99 cross-development tools. Though I had to make certain modifications to the latter, mainly to permit the extensive use of non-ASCII (128-159 and 176-198) characters in my program source.
×
×
  • Create New...