Jump to content
IGNORED

Hacking your way out of the TI-Basic sandbox


retroclouds

Recommended Posts

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 :D

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 :roll:

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 :cool:

Link to comment
Share on other sites

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

Link to comment
Share on other sites

  • 3 weeks later...

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

Link to comment
Share on other sites

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 :roll:

 

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 by Vorticon
Link to comment
Share on other sites

  • 1 month later...

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 :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 2 years later...

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

  • Like 1
Link to comment
Share on other sites

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. :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...