+retroclouds Posted October 7, 2010 Share Posted October 7, 2010 Here's a quick question: would it be possible to run an assembly language program from an unexpanded TI-99/4A without using an external device such as a cartridge (mini memory), memory expansion, etc. Suppose all you have is a bare TI-99/4A with a cassette player. Would it be possible to break out of the TI-Basic "sandbox" and run a machine code program? I could image you can write a basic program that reads a file from the cassette player into VDP memory. This file could contain a small machine code program. The question is how would you copy the machine code program into scratch-pad memory and direct the program counter there so that it starts executing the machine code program. I wonder if there are any bugs in the TI-Basic commands that could be misused for accomplishing just that. I'm sure the details must be in TI-Intern somewhere, but it would require a profound knowledge of both the GPL and TI-Basic interpreter. I don't see a real use, but it's a geek idea anyway Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 7, 2010 Share Posted October 7, 2010 The problem is, unexpanded TI-BASIC does not have any commands to allow you access to the only memory you could use to execute the machine code, i.e. scratch pad. You would have to get the code into some part of unused scratch pad, then branch to it somehow. The only way I can think of would be to find a way to overflow something. However, for all the effort I don't think it would be worth it. Matthew Quote Link to comment Share on other sites More sharing options...
Bones-69 Posted October 7, 2010 Share Posted October 7, 2010 This question is right out of my league but if it was/is possible it would have rocked the world of a lot of early TI users with basic set-ups. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 7, 2010 Share Posted October 7, 2010 Well, even if someone does not have a PEB, it is usually not too much to ask them to plug in a cartridge. The XB or EA carts are pretty much universally expected. I really don't know how much use you could get with the limited memory you could actually have in the scratch pad. You're talking less than 100 bytes probably, and not contiguous. Matthew Quote Link to comment Share on other sites More sharing options...
rocky007 Posted October 7, 2010 Share Posted October 7, 2010 Ti-Basic is bugged and it's probably possible to create a exploit branching to ASM code. Quote Link to comment Share on other sites More sharing options...
+acadiel Posted October 8, 2010 Share Posted October 8, 2010 Ti-Basic is bugged and it's probably possible to create a exploit branching to ASM code. That's what I was thinking... there has to be a jailbreak exploit. :-) 1 Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted October 8, 2010 Share Posted October 8, 2010 Ti-Basic is bugged and it's probably possible to create a exploit branching to ASM code. That's what I was thinking... there has to be a jailbreak exploit. :-) I hope not, the code was very well debugged, and you got to fool two levels, the basic code on top of the gpl code. There is some doors opened when you insert certain modules, as they add CALLS into the basic system. But stock TI-Basic with no modules pulled in is very air-tight. If I can come across a possible bug, I yet you know, I got the full original source code around here someplace still. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 8, 2010 Share Posted October 8, 2010 You would need two kinds of exploits. One to get code into scratch pad at a certain memory address, and another to branch to that code. Also, you have to do this in such a way that you don't destroy the BASIC environment, since, after all, you have less than 256 bytes to do whatever it is you need to do, and thus I'm sure at some point you will need to return to BASIC. While it might be possible, I can't imagine it being very practical once you found the required bugs. Matthew Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 8, 2010 Share Posted October 8, 2010 If I can come across a possible bug, I yet you know, I got the full original source code around here someplace still. Not *THAT* I would like to see! Full source to the BASIC Interpreter. Assuming you are talking about something other than a disassembled dump? Like source with comments, variable names, etc.? Matthew Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted October 8, 2010 Author Share Posted October 8, 2010 You would need two kinds of exploits. One to get code into scratch pad at a certain memory address, and another to branch to that code. Also, you have to do this in such a way that you don't destroy the BASIC environment, since, after all, you have less than 256 bytes to do whatever it is you need to do, and thus I'm sure at some point you will need to return to BASIC. While it might be possible, I can't imagine it being very practical once you found the required bugs. Matthew I don't see a pratical use either, but the geek factor is there anyway If I would do something in that direction, I would not let it return to BASIC. That way you'd have 256 bytes of scratchpad to your disposal. Would be more than enough for doing a sprite demo There is that one TI-Basic game that loads from cassette tape and uses a sprite. That was pretty clever. It was discussed on the Y! group a while ago. Yeah, my next game will be on cassette tape instead of cartridge. Hhmm, no not really Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted October 8, 2010 Author Share Posted October 8, 2010 Below is the TI-basic game that uses a sprite. Check the Y! thread here . Hello everyone, i found a mistic italian game write in tibasic that use a sprite, his name is morphy!! I never listen firts! This game work only ti99 console and unit cassette with never expansion, but i discovered that work also with ti99 +32K+minimemory and use first this command CALL LOAD(31888,63,255) that seem how a call files(0). For use with only ti99 console first you need write this short program IN TI-BASIC: 100 call clear 110 INPUT "registro(0-7),dato(0-255)?":R,D 120 A=18429-(256*R+D) 130 X$=CHR$(0) 140 OPEN #1:"CS1",OUTPUT,FIXED 150 PRINT #1:X$&X$&X$&X$&X$&X$&CHR$(INT(A/256))&CHR$(A) after run it, you insert this value 5,15 and enter. The program write on cs1 a binary program (you no can list it) that his use is a loader for the next program. MORPHY game program 10 CALL CHAR(144,"D") 20 OPTION BASE 1 30 RANDOMIZE 40 DIM H$(32),F$(6),C$(7) 50 CALL CLEAR 60 READ A,B 70 FOR I=A TO A+B 80 READ A$ 90 CALL CHAR(I,A$) 100 NEXT I 110 IF A THEN 60 120 FOR I=2 TO 32 STEP 2 130 A$=SEG$("0123456789ABCDEF",I/2,1) 140 H$(I-1)=A$&"0" 150 H$(I)=A$&"8" 160 NEXT I 170 FOR I=1 TO 10 180 SC(I)=1000 190 N$(I)="M O R P H Y" 200 NEXT I 210 FOR I=1 TO 6 220 READ F$(I) 230 NEXT I 240 FOR I=1 TO 7 250 READ C$(I),A$ 260 C$(I)=C$(I)&A$ 270 NEXT I 280 GOSUB 1210 290 IF B THEN 360 300 GOSUB 980 310 IF B THEN 360 320 GOSUB 1040 330 IF B THEN 360 340 GOSUB 1110 350 IF B=0 THEN 280 360 CALL SCREEN(14) 370 CALL CHAR(145,"D") 380 S=0 390 O=3 400 R=0 410 X=24 420 Y=23 430 K=X 440 C=4 450 P=0 460 E=400 465 F=0 470 Z=0 480 B=3 490 FOR A=1 TO 9 500 Q(A)=INT(B+2*RND) 510 B=2*(Q(A)=1)-2*(Q(A)=6)-5*(Q(A)<4)-(Q(A)>3) 520 NEXT A 530 Q(10)=7 540 FOR A=1 TO 12 550 CALL COLOR(A,1,1) 560 NEXT A 570 B=16 580 FOR A=23 TO 9 STEP-1 590 T=4*RND>1 600 B=B+T 610 CALL HCHAR(A,3,106,B) 620 CALL HCHAR(A,B+3,36+T*(1+RND)) 630 NEXT A 640 PRINT "jjjjjsvquuvqtjjj#":"svquq_w______qtjj#":"`aba``a_^__]^__jjj$":"defgfeg_r__rr_)j\ jj$" 650 PRINT "ky__ikhijkijjkijjs":"jky_tswquuqqvuquw_":"jjky__`abaa`w_____":"jjjky_egfged____\ __":"jjjjkhhhhhhhhm_hhhhhhhhhhhhh"; 660 T=13.0411 670 GOSUB 1440 680 FOR A=10 TO 30 690 CALL SOUND(-100,55*A, 700 NEXT A 710 GOTO 4250 720 DATA 34,7,C0F0F0F0F0F8F8FE,80C0C0C080DCFCFE,80C0E0E0E0C0C0C,0101030707777FFF,070F0F0F\ 1F3F3FFF,03030707070F0F07 730 DATA 0C52272717D2B01,40C0201C1E0F0F07,60,2,60106808D2252418,FFFFFFFFFFFFFFFF,,91,18,3\ C18DBBD7E3C183C,00000080E3FFFFFF,,, 740 DATA FFFF7FFE76561C1C,FFBB2F2B23230202,FFDFFF5E5C1C1818,1818181818181818,181858585C54\ 7EFF,1010909494B5F5FF 750 DATA 1818181C3D3575FF,101111153537B7FF,FFFFFFDF49,FEFAF0E0A08,,7F3F2F070501,FFFFFFFAF\ 0D0C08,FFFFFF7F2F0701 760 DATA 112,13,00808185A5B5B7F7,FF75756424242020,181818383C7C7EFF,FEFEFAF8E8A8888,FF7F5F\ 5F1B090101 770 DATA DF9D951514141404,FFFF7D5C5C585858,5858484808080808,,F0F0F0F0FFFFFFFF,0F0F0F0FFFF\ FFFFF 780 DATA 00384492A2924438,0008081,0010281,128,13,7CD4D7FFFC382433 790 DATA 7CD4D7FFFC38684C,3E2BEBFF3F1C24CC,3E2BEBFF3F1C1632,0C0C9FF93F79DF1E,4C6838FCFFD7\ D47C,78FB9EFC9FF9303 800 DATA 1C3E6B497F2A141C,6010680850222418,001B242320D2120C,002828104A322418,001818104833\ 2418,3C3C7EA5A5A5A5A5 810 DATA 3C3C7EA5A5995A5A,153,2,0F09CD81FF7C187C,103810547C7C287C,FEAAFE7C3810107C,0,-1,E\ 00F,E10F,E20F,E30F,EC0D,ED0D 820 DATA jj__vvuvquqqvuququuqquvutjjjjt__ww_w__bab``___]__^w_pjjjj_a`ab`___c=dcc__<r__r_)\ jsvjj_=c=cc_zlc=hcclhijkijkis_wj 830 DATA j_=c=ffzisc==dfquuquuqqu___jjp=c=_zij(fgg_____________pjjjedgzijjhhhhm_lhy_<<_<_\ _[jjjjkhhijjjjjjjj_jjkhhhhhhhijj 840 DATA js__tjjsvuuquqjjvvuqjjsqvvtjs_`a_vv_w_____qv_w__uq__ww_t_bc=bww__zlhh__w________\ ____ 850 DATA pcc=cb`_zijsw_____^_^]______jfdgdffzijj[__<<_<r_rr__<__(jkhhhhhijjjkhhhhhijhjjkh\ m_li 860 DATA suqqvtsuquqqus_tvququuququjj___________]_ba`a_]`ba`___uj[_________<r_e=cg_red=c_\ _(_jhmy__lm__>ijkh=clijkh=c>lm_j 870 DATA jjky_tv__vququ=cqjvud=ctqu_tjjjky_w]^w_]__ef_jw__ef_^___jjjjky_rr__r<____j[_<<__\ r__[jjjjjkijjkijkhhhijkhhhhij_hi 880 DATA squqvtjjjjuvq__tjsvjjvuvuqvj_`baw_quuq_w_`bau_wuqw_w__wj_cc=`_]_]^_a`=c=a____^__\ __(j 890 DATA [fc=f_r_rr_edgfeg<<_<r__zhijkmdglijhjjkhhhhhhhhhijkhijjj 900 DATA jsuqququuqvquququuqvquuqu_tjs_)____^_____]^__ba`abab`a_t__lmy_<r_____rr__f=cgdef\ c=`a__qvkhijk>__ijjkhh 910 DATA efzhy_d=c=____ujsq___]_ququ__zijky_=c=____(j[_<<_r<_____zijjjkyefgkm_lijkhhhijkh\ hhhhijjjjjkhhi 920 DATA suqququuqvvuquuquvquuqus_tv`b__[____ww____]^_w_____^__wccalhmy____`a__rr_______r\ __(cc=svtky___c=zijjkmy_lhij_licc=bw_jkm>_chiuquv 930 DATA jky_tjs_vvcc=ca_quuv_c=w___wqjky_q__wwcc=c=______dg__^___jjky____pfdefg<<_<r_<<_\ _r__[jjjky___jkhhhhhhhijkhhm_jkhijjjjkhhij 940 DATA js__tjjjsuqvvs_tjjjjjjjsv_tjs____uvq___ww___quvquuv_w__v______w___________w___w_\ ___w 950 DATA khhm\\\\\\\\\lm\\\\\\\\\\lhi 960 DATA 409,508,606,301 970 DATA 4470A70F5470A10F,6470AD0F7470A50F,4488AF0F5488B60F,6488A50F7488B20F, 980 CALL SCREEN(12) 990 C=2.09 1000 GOSUB 1670 1010 PRINT TAB(10);"ISTRUZIONI:": : :"RIPORTA ALLA LUCE I 3 CIMELI": :"DELLA CIVILTA| PERDUTA DI": :"KHNOS.": :"USA:" 1020 PRINT:" S SINISTRA": :" D DESTRA": :" E SALTARE O SALIRE": :" Q BUTTARE CIBO": :" P PUNTEGGIO": : : : 1030 GOTO 1720 1040 CALL SCREEN(14) 1050 PRINT TAB(10);"CLASSIFICA" 1060 FOR I=1 TO 10 1070 PRINT:SC(I);TAB(10);N$(I) 1080 NEXT I 1090 PRINT: : 1100 GOTO 1720 1110 CALL SCREEN(5) 1120 CALL COLOR(2,9,16) 1130 CALL COLOR(8,13,16) 1140 CALL COLOR(16,11,16) 1150 C=5.16 1160 GOSUB 1670 1170 PRINT TAB(;"TABELLA PUNTI": : :" ) COSCIOTTO": : :" [ ANFORA 200 PTI" 1180 PRINT: :" ";CHR$(154);" CORONA 800 PTI": : :" ";CHR$(155);" CALICE 800 PTI": : :" "; 1190 PRINT CHR$(153);" LAMPADA 800 PTI": : :" ( FRUTTO 150 CAL": : : 1200 GOTO 1720 1210 CALL SCREEN(2) 1220 C=8.02 1230 GOSUB 1670 1240 CALL COLOR(13,14,1) 1250 CALL COLOR(14,1,1) 1260 CALL HCHAR(4,1,136,224) 1270 FOR I=6 TO 8 1280 CALL HCHAR(I,5,32,24) 1290 NEXT I 1300 A$="M O R P H Y" 1310 FOR I=1 TO 16 1320 CALL HCHAR(7,8+I,131+I-4*INT(I/4)) 1330 CALL SOUND(-400,348-8*I,6) 1340 CALL HCHAR(7,8+I,ASC(SEG$(A$,I,1))) 1350 NEXT I 1360 C=INT(12*RND+3) 1370 CALL COLOR(14,C,C) 1380 FOR I=6 TO 30 1390 CALL SOUND(-100,110,I,165,I,220,I) 1400 NEXT I 1410 A$="A9{ 1984 TESIOWARE" 1420 GOSUB 1610 1430 GOTO 1720 1440 A=100*(T-INT(T)) 1450 B=100*(A-INT(A)) 1460 CALL COLOR(1,T, 1480 CALL COLOR(8,6,A) 1490 CALL COLOR(9,A,2) 1500 CALL COLOR(10,B,T) 1510 CALL COLOR(11,T,A) 1520 CALL COLOR(12,B,A) 1530 CALL COLOR(13,16,A) 1540 CALL COLOR(14,2,A) 1550 CALL COLOR(16,11,T) 1560 CALL SCREEN(T) 1570 FOR B=2 TO 7 1580 CALL COLOR(B,2,A) 1590 NEXT B 1600 RETURN 1610 T=ASC(A$)-48 1620 Z=ASC(SEG$(A$,2,1))-51 1630 FOR I=3 TO LEN(A$) 1640 CALL HCHAR(T,Z+I,ASC(SEG$(A$,I,1))) 1650 NEXT I 1660 RETURN 1670 A=100*(C-INT(C)) 1680 FOR B=1 TO 12 1690 CALL COLOR(B,C,A) 1700 NEXT B 1710 RETURN 1720 PRINT " PREMI UN TASTO PER INIZIARE"; 1730 FOR I=0 TO 99 1740 CALL KEY(3,A,B) 1750 IF B THEN 1770 1760 NEXT I 1770 CALL CLEAR 1780 CALL VCHAR(1,31,31,96) 1790 RETURN 1800 B=4 1810 C=25 1820 A$="jjjjjjjjjjjjjjjjjjjjjjjjjjjj" 1830 CALL HCHAR(Y,X,130-D) 1840 CALL CHAR(144,"D") 1850 FOR A=1 TO 19 1860 F=INT(-2*RND*(B<12)) 1870 T=-INT(-2*RND*(C>17)) 1880 PRINT SEG$(A$,1,B);CHR$(36-F*(1+RND));TAB(C);CHR$(39+T*(1+RND));SEG$(A$,1,28-C) 1890 B=B+F 1900 C=C+T 1910 NEXT A 1920 PRINT A$; 1930 FOR A=4 TO 6 1940 CALL HCHAR(24,B+A,149+A) 1950 NEXT A 1960 CALL HCHAR(3,X,95) 1970 F=0 1990 A=16 2000 B=23 2010 W=0 2020 GOTO 3760 2030 IF E<0 THEN 2340 2040 CALL SOUND(-80,-1,E) 2050 FOR I=20 TO E STEP-.05 2060 NEXT I 2070 IF P=11 THEN 3850 ELSE 4380 2080 CALL CHAR(144,H$(Y-1)&H$(X)&"E40D") 2090 FOR B=0 TO 2 2100 FOR A=136 TO 139 2110 CALL HCHAR(Y,X,A) 2120 CALL SOUND(-400,250-A,0) 2130 NEXT A 2140 NEXT B 2150 CALL HCHAR(Y,X,60) 2160 GOTO 2340 2170 A$=H$(Y)&H$(X)&F$(3-C) 2180 B$=H$(INT(B))&H$(INT(A)) 2190 FOR C=1E3 TO 8E3 STEP 1E3 2200 I=I=0 2210 CALL CHAR(144,B$&F$(6+I)&A$) 2220 CALL SOUND(-600,C,4) 2230 NEXT C 2240 GOTO 2340 2250 X=X-D 2260 Y=Y+1 2270 A$=H$(Y-1)&H$(X)&"E" 2280 RESTORE 960 2290 FOR A=550 TO 220 STEP-110 2300 READ B$ 2310 CALL SOUND(-400,A,6) 2320 CALL CHAR(144,A$&B$) 2330 NEXT A 2340 CALL CHAR(144,H$(Y-1)&H$(X)&"E70F") 2350 FOR A=0 TO 30 2360 CALL SOUND(-200,110,A,-5,A) 2370 NEXT A 2390 O=O-1 2400 IF O<0 THEN 2460 2405 IF F=3 THEN 2910 2408 E=400 2410 IF P=11 THEN 1990 2420 Y=23 2430 X=K 2440 C=3 2450 GOTO 4250 2460 RESTORE 970 2470 FOR I=144 TO 147 2480 READ A$ 2490 CALL CHAR(I+1,"D") 2500 CALL CHAR(I,A$) 2510 NEXT I 2520 FOR I=21 TO 23 2530 CALL HCHAR(I,5,95,24) 2540 NEXT I 2550 A$="F6PUNTEGGIO_TOTALE:_"&STR$(S) 2560 GOSUB 1610 2570 GOSUB 1730 2580 CALL CHAR(144,"D") 2590 FOR I=1 TO 10 2600 IF S>SC(I)THEN 2630 2610 NEXT I 2620 GOTO 350 2630 CALL SCREEN(11) 2640 C=2.01 2650 GOSUB 1670 2660 PRINT "BRAVO!":"SEI ";STR$(I);"} NELLA CLASSIFICA":"DI OGGI: SCRIVI IL TUO NOME:" 2670 FOR A=9 TO I STEP-1 2680 N$(A+1)=N$(A) 2690 SC(A+1)=SC(A) 2700 NEXT A 2710 INPUT A$ 2720 N$(I)=SEG$(A$,1,16) 2730 SC(I)=S 2740 GOSUB 1770 2750 GOSUB 1040 2760 GOTO 350 2770 W=0 2780 Z=Z=0 2790 IF Z THEN 2820 2800 CALL CHAR(62,"819999DBFFDB7E3C") 2810 GOTO 4290 2820 CALL CHAR(62,"003C7EFFFFDB7E3C") 2830 GOTO 4290 2840 S=S+600 2850 FOR I=1 TO 1.4 STEP .1 2860 CALL SOUND(-100,220*I,4) 2870 CALL SOUND(-100,292*I,4) 2880 NEXT I 2890 CALL HCHAR(3,F+2,K) 2900 IF F<3 THEN 3760 2910 FOR I=2 TO 22 2920 CALL SOUND(-200,110*I,4,55*I,4) 2930 NEXT I 2940 CALL CHAR(144,"D") 2950 FOR A=20 TO 24 2960 CALL HCHAR(A,1,95,14) 2970 NEXT A 2980 A$="E3ENERGIA:"&STR$(E) 2990 GOSUB 1610 3000 A=E*10 3010 A$="G3BONUS:"&STR$(A) 3020 GOSUB 1610 3030 S=S+A 3040 FOR I=0 TO 9 3050 FOR A=9 TO 16 3060 CALL COLOR(16,A,2) 3070 CALL SOUND(-400,A*440,18) 3080 NEXT A 3090 NEXT I 3100 GOSUB 1770 3110 GOTO 410 3120 S=S+200 3130 F=F+1 3140 K=T 3150 FOR T=220 TO 660 STEP 55 3160 CALL SOUND(-100,T,4) 3170 NEXT T 3180 CALL HCHAR(Y,X,106) 3190 Y=Y-1 3200 GOTO 3780 3210 FOR A=660 TO 330 STEP-110 3220 CALL SOUND(-100,A,4) 3230 NEXT A 3240 FOR A=0 TO 30 STEP 2 3250 CALL SOUND(-100,660,A) 3260 NEXT A 3270 S=S+200 3280 CALL HCHAR(Y,X,95) 3290 GOTO 4290 3300 R=R+1 3310 GOTO 3330 3320 E=E+150 3330 FOR A=0 TO 3 3340 CALL SOUND(-100,523,4) 3350 CALL SOUND(-100,440,4) 3360 NEXT A 3370 GOTO 3280 3380 CALL HCHAR(1,3,95,28) 3390 A$="13PTI_"&STR$(S)&"___EN._"&STR$(E)&"___)_"&STR$(R) 3400 GOSUB 1610 3410 CALL HCHAR(1,31-O,128,O) 3420 IF P=11 THEN 3780 ELSE 4290 3430 IF F THEN 3480 3440 F=INT(2*RND+1) 3450 CALL CHAR(92+F,"2856AABA1A90121") 3460 CALL SOUND(-4E3,-5,24) 3470 GOTO 4310 3480 CALL CHAR(92+F,"") 3490 CALL SOUND(-1,-6,30) 3500 F=0 3510 GOTO 4310 3520 IF T<0 THEN 2250 3530 Y=Y-T 3540 X=X-D 3550 CALL SOUND(-60,-3,4) 3560 GOTO 4070 3570 X=X-D 3580 CALL SOUND(-20,-2, 3590 GOTO 4270 3600 IF R<1 THEN 3780 3610 R=R-1 3620 C=X 3630 D=Y 3640 A=INT(A) 3650 B=INT(B) 3660 CALL SOUND(-4E3,-8,16) 3670 C=C+SGN(A-C) 3680 D=D+SGN(B-D) 3690 CALL CHAR(145,H$(D)&H$(C)&"8906D") 3700 IF C-A+D-B THEN 3670 3710 CALL SOUND(-10,880,10) 3720 CALL CHAR(145,"D") 3730 E=E-10 3740 W=14 3750 GOTO 3780 3760 K=0 3770 Y=5 3780 CALL KEY(0,T,T) 3790 IF T=80 THEN 3380 3800 IF T=81 THEN 3600 3810 C=(T=83)-(T=68) 3820 D=(T=69)-(T=-1) 3830 E=E-2 3840 IF E<20 THEN 2030 3850 X=X+C 3860 Y=Y+D 3870 CALL GCHAR(Y,X,T) 3880 IF(T=32)+(T=92)THEN 3940 3890 IF(T=95)*K THEN 2840 3900 IF(T>152)*(K=0)THEN 3120 3910 X=X-C 3920 Y=Y-D 3930 CALL SOUND(-40,-3,4) 3940 W=W-1 3950 IF W>0 THEN 3980 3960 A=A+.6*SGN(X-A) 3970 B=B+.6*SGN(Y-B) 3980 I=I=0 3990 CALL CHAR(144,H$(B)&H$(A)&F$(6+I)&H$(Y)&H$(X)&F$(3-C)) 4000 IF(INT(A)=X)*(INT(B)=Y)THEN 2170 ELSE 3780 4010 IF A-62 THEN 4030 4020 IF Z THEN 4290 ELSE 2260 4030 IF Y=23 THEN 4090 4040 Y=Y+1 4050 CALL CHAR(144,H$(Y)&H$(X)&F$(C)) 4060 IF A=60 THEN 2080 4070 CALL GCHAR(Y+1,X,A) 4080 IF A<104 THEN 4030 ELSE 4260 4090 P=P+1 4100 IF P-3 THEN 4130 4110 T=7.1011 4120 GOSUB 1440 4130 IF P-6 THEN 4160 4140 T=5.0815 4150 GOSUB 1440 4160 IF P-9 THEN 4200 4170 T=2.1504 4180 GOSUB 1440 4190 CALL COLOR(8,8,15) 4200 IF P=11 THEN 1800 4210 PRINT C$(Q(P)); 4220 K=X 4230 GOTO 4260 4240 Y=Y-1 4250 CALL CHAR(144,H$(Y)&H$(X)&F$(C)) 4260 CALL SOUND(-1,2E4,0) 4270 W=W+1 4280 IF W>7 THEN 2770 4290 CALL KEY(0,A,B) 4300 IF RND<.1 THEN 3430 4310 IF A=69 THEN 4510 4320 IF A=80 THEN 3380 4330 D=(A=83)-(A=68) 4340 IF B=0 THEN 4270 4350 S=S+1 4360 E=E-2 4370 IF E<20 THEN 2030 4380 I=I=0 4390 X=X+D 4400 C=I-D+3 4410 CALL GCHAR(Y,X,A) 4420 IF A=121-(D=1)THEN 4240 4430 IF(A=31)+(A=114)+(A=106)THEN 3570 4440 CALL CHAR(144,H$(Y)&H$(X)&F$(C)) 4450 IF A=91 THEN 3210 4460 IF A=60 THEN 2080 4470 IF A=40 THEN 3320 4480 IF A=41 THEN 3300 4490 CALL GCHAR(Y+1,X,A) 4500 IF A<104 THEN 4010 ELSE 4260 4510 E=E-10 4520 FOR T=-1 TO 1 4530 Y=Y+T 4540 X=X+D 4550 CALL GCHAR(Y,X,A) 4560 IF(A=92+F)*F THEN 2270 4570 IF(A>103)+(A=31)THEN 3520 4580 IF A=60 THEN 2080 4590 CALL CHAR(144,H$(Y)&H$(X)&F$(C)) 4600 NEXT T 4610 GOTO 4490 When ti99 read this program on cassette from cs1 on screen show strange carachter but seem normal, and after run you have a first game in tibasic that use a sprite with only ti99 console and cassette recorder!!!! For use with minimory and a 32k expansion put this instruction 15 CALL PEEKV(-753,X) in listate game and no use first program. Remember use a special call load write first. I like if you test this program and write a comment. Greetings at all. ******** P.s. sorry for my english :-p Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 8, 2010 Share Posted October 8, 2010 That Morphy program looks like it might be worth digging into. If they found a way to access the VDP registers, you might be able to get access to scratch pad as well. I was thinking yesterday, and inspired by the Minimal 8-bit CPU, that if instead of trying to write a game or useful program in the 256 bytes of scratch pad, write a byte code interpreter, like a stripped down GPL. That way you could use BASIC's DATA, CHAR, HCHAR, and VCHAR statements to get the byte code program into VDP RAM, then load the interpreter into scratch pad using the exploit. The interpreter takes over and starts executing your program from VDP RAM just like GPL "runs" from GROM. I think this would make a good challenge. 256 bytes to make a byte code interpreter with enough power to write games. The compiler should probably be a PC based program, and maybe a port to the actual 99/4A once it is working. Probably strongly typed with 3 variable types: byte, word, base-100 floating point (to use the console's routines). Let's see, what would be the minimum useful set of instructions? load and store memory, VRAM and conventional compare and branch logical arithmetic input and output for joystick / keyboard But even that might be too much for 256 bytes, but you never know. Matthew Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted October 8, 2010 Author Share Posted October 8, 2010 That Morphy program looks like it might be worth digging into. If they found a way to access the VDP registers, you might be able to get access to scratch pad as well. I was thinking yesterday, and inspired by the Minimal 8-bit CPU, that if instead of trying to write a game or useful program in the 256 bytes of scratch pad, write a byte code interpreter, like a stripped down GPL. That way you could use BASIC's DATA, CHAR, HCHAR, and VCHAR statements to get the byte code program into VDP RAM, then load the interpreter into scratch pad using the exploit. The interpreter takes over and starts executing your program from VDP RAM just like GPL "runs" from GROM. I think this would make a good challenge. 256 bytes to make a byte code interpreter with enough power to write games. The compiler should probably be a PC based program, and maybe a port to the actual 99/4A once it is working. Probably strongly typed with 3 variable types: byte, word, base-100 floating point (to use the console's routines). Let's see, what would be the minimum useful set of instructions? load and store memory, VRAM and conventional compare and branch logical arithmetic input and output for joystick / keyboard But even that might be too much for 256 bytes, but you never know. Matthew Yes, that was what I was thinking about too with the work on spectra: a "mini" interpreter that runs your (game-)programs from VDP memory. If the interpreter would be able to "swap" part of scratchpad memory with the VDP, I'm sure you could accomplish quite a bit. Dunno if it would be worth to tap the console routines though. Mainly because of the specific locations it requires in scratchpad memory. Let's dig out the cassette player No better not, there's already too much on my plate. But it is tempting Quote Link to comment Share on other sites More sharing options...
rocky007 Posted October 10, 2010 Share Posted October 10, 2010 i checked how this tricks worked (fake header CS1), and it's really amazing. unfortunally, it's limited to the sprite table, but it prooves that everything is not locked. I remember when i was 10 years old, i found a special sequence ( few letters ) that crash the TI99 under TI basic. It was really amazing, bec if i remember well, in crashing, i had some sprite everywhere on the screen with strange char everywhere, it was little little special effect. This sequence was based on the the special command to desactivate something in math to accelerate the TI basic.. ( #???* or something like this) sorry, i don't remember exactly Quote Link to comment Share on other sites More sharing options...
bfollett Posted October 25, 2010 Share Posted October 25, 2010 This is somewhat unrelated and perhaps it's well known now, but I remember I came across a bad TI extended basic command you could issue that would drop you out of extended basic and into regular basic with your code still intact. If you listed your code you would see garbled characters for any extended basic commands, but if the code was entirely TI basic compliant it would run. I wish I remembered what the line of code was, but I remember I would use extended basic even if I was programming a standard basic program because it was faster and then I would issue the command to switch and test it under regular basic. Bob Quote Link to comment Share on other sites More sharing options...
Opry99er Posted October 26, 2010 Share Posted October 26, 2010 Fascinating stuff.... Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted November 1, 2010 Share Posted November 1, 2010 (edited) You would need two kinds of exploits. One to get code into scratch pad at a certain memory address, and another to branch to that code. Also, you have to do this in such a way that you don't destroy the BASIC environment, since, after all, you have less than 256 bytes to do whatever it is you need to do, and thus I'm sure at some point you will need to return to BASIC. While it might be possible, I can't imagine it being very practical once you found the required bugs. Matthew I don't see a pratical use either, but the geek factor is there anyway If I would do something in that direction, I would not let it return to BASIC. That way you'd have 256 bytes of scratchpad to your disposal. Would be more than enough for doing a sprite demo There is that one TI-Basic game that loads from cassette tape and uses a sprite. That was pretty clever. It was discussed on the Y! group a while ago. Yeah, my next game will be on cassette tape instead of cartridge. Hhmm, no not really That game is called Morphy by Ermanno Alekine and is available on the TI Gameshelf site. Very cool hack. It runs perfectly fine under Win994a using the included cassette emulator. Edited November 1, 2010 by Vorticon Quote Link to comment Share on other sites More sharing options...
kl99 Posted December 28, 2010 Share Posted December 28, 2010 While it might be possible, I can't imagine it being very practical once you found the required bugs. I thought about this and the most practical use I could think of would be the possibility of saving the cartridge content to disk or to tape. Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted December 28, 2010 Author Share Posted December 28, 2010 While it might be possible, I can't imagine it being very practical once you found the required bugs. I thought about this and the most practical use I could think of would be the possibility of saving the cartridge content to disk or to tape. Have to admit that I never dumped any cartridge ROMS/GROMS until now. But I think these are the steps involved for dumping a cartridge ROM: 1) Write an assembly language program to dump the memory area >6000->7FFF and load this program into the high memory expansion area (e.g. >A000). 2) Poke the address of the new register workspace at memory location >FFFC Poke the address of the assembly language program (e.g. >A000) into memory location >FFFE (vector for load-interrupt) 3) Insert the cartridge to dump into the cartridge slot 4) Trigger the load-interrupt hardware signal (*) (*) Check Thierry's page for details. You need a hardware switch for (4), e.g. I have a speech synthesizer with a load-interrupt switch hacked into it. There is a problem though: when you insert a cartridge, the TI-99/4A is reset and I think that always clears high-memory. I suppose this could be prevented by disabling the reset signal on the cartridge pcb. Hoping that someone with hardware knowledge can chime in and give some more details Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 28, 2010 Share Posted December 28, 2010 Most people disabled the reset just by taping over the reset pin on the cartridge (pin 1, was it?). That way you could write your dumper, load it in Editor/Assembler, have it wait for a key, swap carts, then dump. You don't even need a LOAD interrupt then. Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted December 29, 2010 Author Share Posted December 29, 2010 Most people disabled the reset just by taping over the reset pin on the cartridge (pin 1, was it?). That way you could write your dumper, load it in Editor/Assembler, have it wait for a key, swap carts, then dump. You don't even need a LOAD interrupt then. Now that's a nice one! Just comes to mind that if you have a GRAM Kracker, it has the software built-in for dumping the cartridge. The GK sports a cartridge slot where you plugin the cartridge to dump without issuing the reset signal. Guess that's why the GK has an own reset switch. Check here. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 29, 2010 Share Posted December 29, 2010 With my setup in heyday consisting of console, cassettedeck, mini memory and 32K standalone, I was able to run in high, exchange carts, copy and examine - the console didn't reset in like 1 out of 4. Also seemed to work better if the exchange was rapid. Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted October 28, 2013 Author Share Posted October 28, 2013 Thank you @Vorticon for posting this. I thought it would be wise to make a cross-post here so that it does not got lost in history I saw this today on the Yahoo listserv, and I thought it was fascinating. Essentially the author, James Abbatiello, is able to coerce TI BASIC to run a small assembly language program. Take a look: 10 REM Escape the BASIC sandbox 20 REM by James Abbatiello <abbeyj@...> 30 REM Displays an animated Hello, World! 40 REM message using machine language. 50 REM Works even without Extended BASIC 60 REM and without the 32K memory expansion. 100 CALL CLEAR 110 PRINT "PRESS" 120 PRINT "1 FOR TI-99/4A" 130 PRINT "2 FOR TI-99/4A (alt)" 140 PRINT "3 FOR TI-99/4A V2.2" 150 CALL KEY(5,C,S) 160 IF (C < 49) + (C > 51) THEN 150 170 PRINT "INITIALIZING ..." 180 V(0)=885 190 V(1)=882 200 V(2)=846 210 L=V(C-49) 220 A$=CHR$(INT(L/256))&CHR$(L-256*INT(L/256)) 230 FOR I = 1 TO 126 240 READ C 250 A$=A$&CHR$© 260 NEXT I 270 OPEN #1:A$ 800 DATA 128,168,165,172,172,175,140,128 810 DATA 183,175,178,172,164,129,0,0 820 DATA 0,0,0,0,0,0,0,0 830 DATA 0,0,0,0,0,0,0,0 840 DATA 0,0,0,0,0,0,0,74 850 DATA 0,0,0,0,0,0,0,0 860 DATA 0,0,0,0,131,130,2,0 870 DATA 2,244,2,11,64,0,6,0 880 DATA 19,250,208,111,252,0,10,17 890 DATA 23,252,215,224,131,247,2,2 900 DATA 131,76,215,203,5,139,208,114 910 DATA 19,242,219,193,255,254,16,251 920 DATA 0,0,0,0,0,0,0,0 930 DATA 0,0,0,0,0,0,0,0 940 DATA 0,0,0,0,0,0,0,0 950 DATA 0,0,0,0,0,0 The first thing we need is the address of some specific code in GROM but this unfortunately varies in the different GROM versions and I have no way to detect which value is appropriate. I resorted to asking the user. Armed with this, we use it as the first two bytes of a long string. Then we take this string and try to OPEN it. For the following explanation you might want to follow along in your own copy of TI Intern. When we try to open this weird filename we'll end up at G>401E (Basic OPEN). From there we'll call G>4BA1 to build a PAB. There's a bug here but not one that I exploit. The code takes the length of the input string and adds >0E to it to compute the length of the entire PAB and then it tries to allocate this much space. Only one byte is used for this length so passing in a long name can cause this calculation to overflow, leading us to allocate less space than needed. We'll end up writing past the end of the allocated space and overwriting something (probably part of the line number table). If we ever want to return to BASIC this would be a problem. The string I use is not long enough to trigger this bug. Eventually we'll try to actually open this file by calling G>03D9 (DSRLNK). This is expecting a string like "DSK1" or "DSK1.FOO" and it wants to find the first period (if any) and then treat the part to the left as the device name. It will copy this device name into the FAC (at >834A) but only if it fits. First it looks for a period and stores its index (or the length of the entire string if there is no period) in >8355. It then uses "CGE @>8355,>08" to check the length and make sure it is 7 bytes or less. However this doesn't work properly for long strings because it is a signed comparison. So if you have a string of length >80 or longer it will still pass this check. Then the code uses "MOVE @>8354 TO @>834A FROM VDP*>8356" to try to copy the device name into the FAC and conveniently copies the entire string, blindly overwriting whatever was there. This is nice for us because it copies our string unmodified right into the scratchpad. Let's take a closer look at that string. Here's a hex dump along with the addresses that it will end up being copied to: Addr Offset 834A 0000 03 ?? 80 A8 A5 AC AC AF 8352 0008 8C 80 B7 AF B2 AC A4 81 835A 0010 00 00 00 00 00 00 00 00 8362 0018 00 00 00 00 00 00 00 00 836A 0020 00 00 00 00 00 00 00 00 8372 0028 00 4A 00 00 00 00 00 00 837A 0030 00 00 00 00 00 00 83 82 8382 0038 02 00 02 F4 02 0B 40 00 838A 0040 06 00 13 FA D0 6F FC 00 8392 0048 0A 11 17 FC D7 E0 83 F7 839A 0050 02 02 83 4C D7 CB 05 8B 83A2 0058 D0 72 13 F2 DB C1 FF FE 83AA 0060 10 FB 00 00 00 00 00 00 83B2 0068 00 00 00 00 00 00 00 00 83BA 0070 00 00 00 00 00 00 00 00 83C2 0078 00 00 00 00 00 00 00 00 0000-0001 is the address in GROM. It can be >0375 (Classic99 and my actual hardware), >0372 (as in TI Intern), or >034E (V2.2). 0002-000F is the string " HELLO, WORLD!" with a leading space and the >60 BASIC screen bias. 0029 is >4A which will overwrite the GPL substack pointer at >8373 0036-0037 contains the address of the entry point of our program (>8382). 0038-0061 contains the actual program: ENTRY LI R0,756 768 - len(" HELLO, WORLD!") LI R11,>4000 VDP write address WSTR DEC R0 at end of screen? JEQ ENTRY if so, start over at top WAITVBL MOVB @->400(R15),R1 wait for vblank SLA R1,1 JNC WAITVBL MOVB @>83F7,*R15 low byte of VDP write address LI R2,>834C address of " HELLO, WORLD!" MOVB R11,*R15 high byte of VDP write address INC R11 WCHAR MOVB *R2+,R1 load byte of string JEQ WSTR done when we hit NUL terminator MOVB R1,@-2(R15) write byte to screen JMP WCHAR The rest of the bytes are just filler/padding. We end up overwriting quite a lot of stuff in the scratchpad including R0 through R4 in the interrupt workspace. After copying the string to the scratchpad the GPL will continue running until it hits RTN or RTNC. The interrupt handler might execute between any of these instructions and update the timer at >8379 or the VDP status byte at >837B so we have to be careful not to rely on having anything in those locations. This bit me at first and I it took a while to figure out why things would work properly one time and not the next. At this point the RTN will pop a GROM address off the GPL subroutine stack. We've set that pointer to >4A so the address will be fetched from >834A. Hopefully we've managed to arrange for that to point at these GPL instructions: DST @>8300,@>8380 Fetch address in >8300 (for XML) XML >F0 and execute This copies our start address from >8380 to >8300 and then calls XML >F0 which jumps to an address stored in >8300. And we're off and running! I don't suppose anybody wants to try their hand at making a more interesting payload for this? -- James Abbatiello 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted October 28, 2013 Share Posted October 28, 2013 I was thinking about this and wondering how it might be turned into something bigger... On a TI BASIC system with 32k expansion available, you could use the scratchpad code as a bootstrap to load assembly into 32k and branch to it. I expect you could load a fair bit of assembly into character definitions.. strings might be possible but you'd need to be able to find them in VDP (taking into account disk systems as well, ideally, so they may move. Perhaps searching with a tag... hell. Maybe even storing it in comments. But what could you do without 32k? Is there enough space in the over-writable scratchpad that if you loaded a bunch of assembly into VDP, you could maybe page "blocks" through scratchpad to execute? Fun challenge, maybe. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted October 28, 2013 Share Posted October 28, 2013 I was thinking about this and wondering how it might be turned into something bigger... On a TI BASIC system with 32k expansion available, you could use the scratchpad code as a bootstrap to load assembly into 32k and branch to it. I expect you could load a fair bit of assembly into character definitions.. strings might be possible but you'd need to be able to find them in VDP (taking into account disk systems as well, ideally, so they may move. Perhaps searching with a tag... hell. Maybe even storing it in comments. But what could you do without 32k? Is there enough space in the over-writable scratchpad that if you loaded a bunch of assembly into VDP, you could maybe page "blocks" through scratchpad to execute? Fun challenge, maybe. DATA statements would be a good place to store the code. You can fit about 160 bytes into a DATA statement..How about loading a short program that stashes the contents of the scratchpad from >8300 to >83BF to a buffer in the VDP. Now you have 192 bytes to play with, 32 more if you use the workspace at >8C00 . Then as Tursi suggests, you could page blocks of code through that part of the scratchpad as needed. You'd need something like VMBR fetch the pages. When finished with assembly restore the scratchpad and return to BASIC. This is a really interesting challenge! I have a couple of ideas that I may try out. 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.