Difference between revisions of "MLX II by Ottis Cowper Ver 1.1"
Jump to navigation
Jump to search
(Created page with "==Code== <syntaxhighlight lang="basic"> 10 rem version 1.1: lines 830,950 modified, lines 485-487 added 100 poke 56,50:clr:dim in$,i,j,a,b,a$,b$,a(7),n$...") |
(→Code) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
==Code== | ==Code== | ||
<syntaxhighlight lang="basic"> | <syntaxhighlight lang="basic"> | ||
− | 10 rem version 1.1: lines 830,950 modified, lines 485-487 added | + | 10 rem version 1.1: lines 830,950 modified, lines 485-487 added |
− | 100 poke 56,50:clr:dim in$,i,j,a,b,a$,b$,a(7),n$ | + | REM ; The version 1.1 update provides the MLX Keypad feature where a 4x4 grid of keys can perform as a keypad to aid in touch-type entry from a magazine. |
+ | |||
+ | REM 55,56 is the Zero Page pointer for the upper boundary of BASIC RAM, instead of being bounded at $A000, it is now $3200 since this BASIC program occupies no additional memory. | ||
+ | REM CLR removes all preexisting variables. Since RUN implicitly performs this action and there are no loops back to this line, I'm not certain why it's here. | ||
+ | REM Arrays are declared: | ||
+ | REM in$ : 11 string elements | ||
+ | REM i : 11 real elements | ||
+ | REM j : 11 real elements | ||
+ | REM a : 11 real elements | ||
+ | REM b : 11 real elements | ||
+ | REM a$ : 11 string elements | ||
+ | REM b$ : 11 string elements | ||
+ | REM a(7) : 7 real elements | ||
+ | REM n$ : 11 string elements | ||
+ | |||
+ | 100 poke 56,50:clr:dim in$,i,j,a,b,a$,b$,a(7),n$ | ||
+ | |||
+ | REM c4 ; Offset of ASCII character '0'=48 | ||
+ | REM c6 | ||
+ | REM c7 | ||
+ | |||
+ | REM These are 'z' constants for determining checksum, exception for | ||
+ | REM z6 which is also used for numerical base conversion | ||
+ | REM z2,z4,z5,z6,z7 | ||
+ | |||
110 c4=48:c6=16:c7=7:z2=2:z4=254:z5=255:z6=256:z7=127 | 110 c4=48:c6=16:c7=7:z2=2:z4=254:z5=255:z6=256:z7=127 | ||
+ | |||
+ | REM 45,46 is the pointer to the start of BASIC variable storage | ||
+ | REM fa is decimal of BASIC variable storage pointer | ||
+ | REM bs is the top of BASIC RAM, function of $0056 | ||
+ | REM h$ is a list of valid hex symbols | ||
+ | |||
120 fa=peek(45)+z6*peek(46):bs=peek(55)+z6*peek(56):h$="0123456789abcdef" | 120 fa=peek(45)+z6*peek(46):bs=peek(55)+z6*peek(56):h$="0123456789abcdef" | ||
+ | |||
+ | REM r$ is Return character. | ||
+ | REM l$ is Cursor Left character. | ||
+ | REM s$ is Space character. | ||
+ | REM d$ is DEL character. | ||
+ | REM z$ is NULL character. | ||
+ | REM t$ is a 13 string of Cursor Right characters. A 13 space TAB? | ||
+ | |||
130 r$=chr$(13):l$="{LEFT}":s$=" ":d$=chr$(20):z$=chr$(0):t$="{13 RIGHT}" | 130 r$=chr$(13):l$="{LEFT}":s$=" ":d$=chr$(20):z$=chr$(0):t$="{13 RIGHT}" | ||
+ | |||
+ | REM Clear all SID registers except master volume, filters. | ||
+ | REM Define master volume and filters with $15, | ||
+ | REM Change the pointer to the IRQ routine from $EA31 to $EA34 (not sure why, skipping ASM code 'JSR $FFEA' which updates software clock?) | ||
+ | |||
140 sd=54272:for i=sd to sd+23:poke i,0:next:poke sd+24,15:poke 788,52 | 140 sd=54272:for i=sd to sd+23:poke i,0:next:poke sd+24,15:poke 788,52 | ||
+ | |||
+ | REM Clear screen, assign large character set, Disable Shift-OS key. | ||
+ | REM Set VIC registers. Make border, then background white. | ||
+ | |||
150 print"{CLR}"chr$(142)chr$(8):poke 53280,15:poke 53281,15 | 150 print"{CLR}"chr$(142)chr$(8):poke 53280,15:poke 53281,15 | ||
+ | |||
+ | REM Draw title screen. | ||
+ | |||
160 print t$" {RED}{RVS} {8 OS-@} "spc(28)" {OFF}{BLU} mlx ii {RED}{RVS} "spc(28)" {BLU}" | 160 print t$" {RED}{RVS} {8 OS-@} "spc(28)" {OFF}{BLU} mlx ii {RED}{RVS} "spc(28)" {BLU}" | ||
170 print"{DOWN}{DOWN}{DOWN} compute!'s machine language editor{DOWN}{DOWN}{DOWN}" | 170 print"{DOWN}{DOWN}{DOWN} compute!'s machine language editor{DOWN}{DOWN}{DOWN}" | ||
+ | |||
+ | REM Draw request for addresses. | ||
+ | |||
180 print"{BLK}starting address{OS-4}";:gosub300:sa=ad:gosub1040:if f then180 | 180 print"{BLK}starting address{OS-4}";:gosub300:sa=ad:gosub1040:if f then180 | ||
190 print"{BLK} ending address{OS-4}";:gosub300:ea=ad:gosub1030:if f then190 | 190 print"{BLK} ending address{OS-4}";:gosub300:ea=ad:gosub1030:if f then190 | ||
+ | |||
+ | REM Ask to clear memory | ||
+ | |||
200 input"{DOWN}{DOWN}{DOWN}{BLK}clear workspace [y/n]{OS-4}";a$:if left$(a$,1)<>"y"then220 | 200 input"{DOWN}{DOWN}{DOWN}{BLK}clear workspace [y/n]{OS-4}";a$:if left$(a$,1)<>"y"then220 | ||
210 print"{DOWN}{DOWN}{BLU}working...";:fori=bs to bs+ea-sa+7:poke i,0:next:print"done" | 210 print"{DOWN}{DOWN}{BLU}working...";:fori=bs to bs+ea-sa+7:poke i,0:next:print"done" | ||
+ | |||
+ | REM Draw Menu | ||
+ | |||
220 printtab(10)"{DOWN}{DOWN}{BLK}{RVS} mlx command menu {DOWN}{OS-4}":print t$"{RVS}e{OFF}nter data" | 220 printtab(10)"{DOWN}{DOWN}{BLK}{RVS} mlx command menu {DOWN}{OS-4}":print t$"{RVS}e{OFF}nter data" | ||
230 print t$"{RVS}d{OFF}isplay data":print t$"{RVS}l{OFF}oad file" | 230 print t$"{RVS}d{OFF}isplay data":print t$"{RVS}l{OFF}oad file" | ||
240 print t$"{RVS}s{OFF}ave file":print t$"{RVS}q{OFF}uit{DOWN}{DOWN}{BLK}" | 240 print t$"{RVS}s{OFF}ave file":print t$"{RVS}q{OFF}uit{DOWN}{DOWN}{BLK}" | ||
+ | |||
+ | REM Menu option action. If not E, D, L, S or Q, then play AngryBuzz then ask again | ||
+ | |||
250 get a$:if a$=n$ then250 | 250 get a$:if a$=n$ then250 | ||
260 a=0:for i=1 to 5:if a$=mid$("edlsq",i,1)then a=i:i=5 | 260 a=0:for i=1 to 5:if a$=mid$("edlsq",i,1)then a=i:i=5 | ||
270 next:on a goto420,610,690,700,280:gosub1060:goto250 | 270 next:on a goto420,610,690,700,280:gosub1060:goto250 | ||
+ | |||
+ | REM Quit. | ||
+ | |||
280 print"{RVS} quit ":input"{DOWN}{OS-4}are you sure [y/n]";a$:if left$(a$,1)<>"y"then220 | 280 print"{RVS} quit ":input"{DOWN}{OS-4}are you sure [y/n]";a$:if left$(a$,1)<>"y"then220 | ||
290 poke sd+24,0:end | 290 poke sd+24,0:end | ||
+ | |||
+ | REM Get address into ad | ||
+ | |||
+ | REM If len!=4, then ad=0, which is invalid | ||
300 in$=n$:ad=0:inputin$:iflen(in$)<>4thenreturn | 300 in$=n$:ad=0:inputin$:iflen(in$)<>4thenreturn | ||
+ | |||
310 b$=in$:gosub320:ad=a:b$=mid$(in$,3):gosub320:ad=ad*256+a:return | 310 b$=in$:gosub320:ad=a:b$=mid$(in$,3):gosub320:ad=ad*256+a:return | ||
320 a=0:for j=1 to 2:a$=mid$(b$,j,1):b=asc(a$)-c4+(a$>"@")*c7:a=a*c6+b | 320 a=0:for j=1 to 2:a$=mid$(b$,j,1):b=asc(a$)-c4+(a$>"@")*c7:a=a*c6+b | ||
330 if b<0 or b>15 then ad=0:a=-1:j=2 | 330 if b<0 or b>15 then ad=0:a=-1:j=2 | ||
340 next:return | 340 next:return | ||
+ | |||
+ | |||
350 b=int(a/c6):print mid$(h$,b+1,1);:b=a-b*c6:print mid$(h$,b+1,1);:return | 350 b=int(a/c6):print mid$(h$,b+1,1);:b=a-b*c6:print mid$(h$,b+1,1);:return | ||
360 a=int(ad/z6):gosub350:a=ad-a*z6:gosub350:print":"; | 360 a=int(ad/z6):gosub350:a=ad-a*z6:gosub350:print":"; | ||
Line 34: | Line 106: | ||
400 print"{DOWN}starting at{OS-4}";:gosub300:if in$<>n$ then gosub1030:if f then400 | 400 print"{DOWN}starting at{OS-4}";:gosub300:if in$<>n$ then gosub1030:if f then400 | ||
410 return | 410 return | ||
+ | |||
+ | REM Enter Data | ||
+ | |||
420 print"{RVS} enter data ":gosub400:if in$=n$ then220 | 420 print"{RVS} enter data ":gosub400:if in$=n$ then220 | ||
430 open3,3:print | 430 open3,3:print | ||
Line 56: | Line 131: | ||
590 ad=ad+8:if ad>ea then close3:print"{DOWN}{BLU}** end of entry **{BLK}{2 DOWN}":goto700 | 590 ad=ad+8:if ad>ea then close3:print"{DOWN}{BLU}** end of entry **{BLK}{2 DOWN}":goto700 | ||
600 f=0:goto440 | 600 f=0:goto440 | ||
+ | |||
+ | REM Display Data | ||
+ | |||
610 print"{CLR}{DOWN}{RVS} display data ":gosub400:if in$=n$ then220 | 610 print"{CLR}{DOWN}{RVS} display data ":gosub400:if in$=n$ then220 | ||
620 print"{DOWN}{BLU}press: {RVS}space{OFF} to pause, {RVS}return{OFF} to break{OS-4}{DOWN}" | 620 print"{DOWN}{BLU}press: {RVS}space{OFF} to pause, {RVS}return{OFF} to break{OS-4}{DOWN}" | ||
Line 64: | Line 142: | ||
670 if a$=s$ then f=f+1:gosub1080 | 670 if a$=s$ then f=f+1:gosub1080 | ||
680 onfgoto630,660,630 | 680 onfgoto630,660,630 | ||
+ | |||
+ | REM Load/Save Data | ||
+ | |||
690 print"{DOWN}{RVS} load data ":op=1:goto710 | 690 print"{DOWN}{RVS} load data ":op=1:goto710 | ||
700 print"{DOWN}{RVS} save file ":op=0 | 700 print"{DOWN}{RVS} save file ":op=0 | ||
Line 98: | Line 179: | ||
1010 ah=int(a/256):al=a-(ah*256):poke193,al:poke194,ah | 1010 ah=int(a/256):al=a-(ah*256):poke193,al:poke194,ah | ||
1020 ah=int(b/256):al=b-(ah*256):poke174,al:poke175,ah:return | 1020 ah=int(b/256):al=b-(ah*256):poke174,al:poke175,ah:return | ||
+ | |||
+ | REM check validity of ending address, using ad as parameter | ||
+ | REM | ||
+ | |||
1030 if ad<sa or ad>ea then1050 | 1030 if ad<sa or ad>ea then1050 | ||
+ | |||
+ | REM Check validity of starting address, using ad as parameter | ||
+ | REM f=0 is success | ||
+ | |||
1040 if (ad>511 and ad<65280) then gosub1080: f=0: return | 1040 if (ad>511 and ad<65280) then gosub1080: f=0: return | ||
+ | |||
+ | REM Error message. Gosub AngryBuzz, draw error, set error flag, return | ||
+ | |||
1050 gosub1060:print"{RVS} invalid address {DOWN}{BLK}":f=1:return | 1050 gosub1060:print"{RVS} invalid address {DOWN}{BLK}":f=1:return | ||
+ | |||
+ | REM AngryBuzz | ||
+ | |||
1060 poke sd+5,31:poke sd+6,208:poke sd,240:poke sd+1,4:poke sd+4,33 | 1060 poke sd+5,31:poke sd+6,208:poke sd,240:poke sd+1,4:poke sd+4,33 | ||
1070 for s=1 to 100:next:goto1090 | 1070 for s=1 to 100:next:goto1090 |
Latest revision as of 03:29, 13 October 2021
Code
10 rem version 1.1: lines 830,950 modified, lines 485-487 added
REM ; The version 1.1 update provides the MLX Keypad feature where a 4x4 grid of keys can perform as a keypad to aid in touch-type entry from a magazine.
REM 55,56 is the Zero Page pointer for the upper boundary of BASIC RAM, instead of being bounded at $A000, it is now $3200 since this BASIC program occupies no additional memory.
REM CLR removes all preexisting variables. Since RUN implicitly performs this action and there are no loops back to this line, I'm not certain why it's here.
REM Arrays are declared:
REM in$ : 11 string elements
REM i : 11 real elements
REM j : 11 real elements
REM a : 11 real elements
REM b : 11 real elements
REM a$ : 11 string elements
REM b$ : 11 string elements
REM a(7) : 7 real elements
REM n$ : 11 string elements
100 poke 56,50:clr:dim in$,i,j,a,b,a$,b$,a(7),n$
REM c4 ; Offset of ASCII character '0'=48
REM c6
REM c7
REM These are 'z' constants for determining checksum, exception for
REM z6 which is also used for numerical base conversion
REM z2,z4,z5,z6,z7
110 c4=48:c6=16:c7=7:z2=2:z4=254:z5=255:z6=256:z7=127
REM 45,46 is the pointer to the start of BASIC variable storage
REM fa is decimal of BASIC variable storage pointer
REM bs is the top of BASIC RAM, function of $0056
REM h$ is a list of valid hex symbols
120 fa=peek(45)+z6*peek(46):bs=peek(55)+z6*peek(56):h$="0123456789abcdef"
REM r$ is Return character.
REM l$ is Cursor Left character.
REM s$ is Space character.
REM d$ is DEL character.
REM z$ is NULL character.
REM t$ is a 13 string of Cursor Right characters. A 13 space TAB?
130 r$=chr$(13):l$="{LEFT}":s$=" ":d$=chr$(20):z$=chr$(0):t$="{13 RIGHT}"
REM Clear all SID registers except master volume, filters.
REM Define master volume and filters with $15,
REM Change the pointer to the IRQ routine from $EA31 to $EA34 (not sure why, skipping ASM code 'JSR $FFEA' which updates software clock?)
140 sd=54272:for i=sd to sd+23:poke i,0:next:poke sd+24,15:poke 788,52
REM Clear screen, assign large character set, Disable Shift-OS key.
REM Set VIC registers. Make border, then background white.
150 print"{CLR}"chr$(142)chr$(8):poke 53280,15:poke 53281,15
REM Draw title screen.
160 print t$" {RED}{RVS} {8 OS-@} "spc(28)" {OFF}{BLU} mlx ii {RED}{RVS} "spc(28)" {BLU}"
170 print"{DOWN}{DOWN}{DOWN} compute!'s machine language editor{DOWN}{DOWN}{DOWN}"
REM Draw request for addresses.
180 print"{BLK}starting address{OS-4}";:gosub300:sa=ad:gosub1040:if f then180
190 print"{BLK} ending address{OS-4}";:gosub300:ea=ad:gosub1030:if f then190
REM Ask to clear memory
200 input"{DOWN}{DOWN}{DOWN}{BLK}clear workspace [y/n]{OS-4}";a$:if left$(a$,1)<>"y"then220
210 print"{DOWN}{DOWN}{BLU}working...";:fori=bs to bs+ea-sa+7:poke i,0:next:print"done"
REM Draw Menu
220 printtab(10)"{DOWN}{DOWN}{BLK}{RVS} mlx command menu {DOWN}{OS-4}":print t$"{RVS}e{OFF}nter data"
230 print t$"{RVS}d{OFF}isplay data":print t$"{RVS}l{OFF}oad file"
240 print t$"{RVS}s{OFF}ave file":print t$"{RVS}q{OFF}uit{DOWN}{DOWN}{BLK}"
REM Menu option action. If not E, D, L, S or Q, then play AngryBuzz then ask again
250 get a$:if a$=n$ then250
260 a=0:for i=1 to 5:if a$=mid$("edlsq",i,1)then a=i:i=5
270 next:on a goto420,610,690,700,280:gosub1060:goto250
REM Quit.
280 print"{RVS} quit ":input"{DOWN}{OS-4}are you sure [y/n]";a$:if left$(a$,1)<>"y"then220
290 poke sd+24,0:end
REM Get address into ad
REM If len!=4, then ad=0, which is invalid
300 in$=n$:ad=0:inputin$:iflen(in$)<>4thenreturn
310 b$=in$:gosub320:ad=a:b$=mid$(in$,3):gosub320:ad=ad*256+a:return
320 a=0:for j=1 to 2:a$=mid$(b$,j,1):b=asc(a$)-c4+(a$>"@")*c7:a=a*c6+b
330 if b<0 or b>15 then ad=0:a=-1:j=2
340 next:return
350 b=int(a/c6):print mid$(h$,b+1,1);:b=a-b*c6:print mid$(h$,b+1,1);:return
360 a=int(ad/z6):gosub350:a=ad-a*z6:gosub350:print":";
370 ck=int(ad/z6):ck=ad-z4*ck+z5*(ck>z7):goto390
380 ck=ck*z2+z5*(ck>z7)+a
390 ck=ck+z5*(ck>z5):return
400 print"{DOWN}starting at{OS-4}";:gosub300:if in$<>n$ then gosub1030:if f then400
410 return
REM Enter Data
420 print"{RVS} enter data ":gosub400:if in$=n$ then220
430 open3,3:print
440 poke198,0:gosub360:if f then print in$:print"{UP}{5 RIGHT}";
450 for i=0 to 24 step 3:b$=s$:for j=1 to 2:if f then b$=mid$(in$,i+j,1)
460 print"{RVS}"b$l$;:if i<24then print"{OFF}";
470 get a$:if a$=n$ then470
480 if(a$>"/"anda$<":")or(a$>"@"anda$<"g")then540
485 a=-(a$="m")-2*(a$=",")-3*(a$=".")-4*(a$="/")-5*(a$="j")-6*(a$="k")
486 a=a-7*(a$="l")-8*(a$=":")-9*(a$="u")-10*(a$="i")-11*(a$="o")-12*(a$="p")
487 a=a-13*(a$=s$):if a then a$=mid$("abcd123e456f0",a,1):goto 540
490 if a$=r$ and((i=0)and(j=1)or f)then print b$;:j=2:next:i=24:goto550
500 if a$="{HOME}" then print b$:j=2:next:i=24:next:f=0:goto440
510 if(a$="{RIGHT}")andf thenprint b$l$;:goto540
520 if a$<>l$ and a$<>d$ or((i=0)and(j=1))then gosub1060:goto470
530 a$=l$+s$+l$:print b$l$;:j=2-j:if j then print l$;:i=i-3
540 print a$;:next j:print s$;
550 next i:print:print"{UP}{5 RIGHT}";:input#3,in$:if in$=n$ then close3:goto220
560 for i=1 to 25 step3:b$=mid$(in$,i):gosub320:if i<25 then gosub380:a(i/3)=a
570 next:if a<>ck then gosub1060:print"{BLK}{RVS} error: reenter line {OS-4}":f=1:goto440
580 gosub1080:b=bs+ad-sa:for i=0 to 7:poke b+i,a(i):next
590 ad=ad+8:if ad>ea then close3:print"{DOWN}{BLU}** end of entry **{BLK}{2 DOWN}":goto700
600 f=0:goto440
REM Display Data
610 print"{CLR}{DOWN}{RVS} display data ":gosub400:if in$=n$ then220
620 print"{DOWN}{BLU}press: {RVS}space{OFF} to pause, {RVS}return{OFF} to break{OS-4}{DOWN}"
630 gosub360:b=bs+ad-sa:fori=bto b+7:a=peek(i):gosub350:gosub380:print s$;
640 next:print"{RVS}";:a=ck:gosub350:print
650 f=1:ad=ad+8:if ad>ea thenprint"{DOWN}{BLU}** end of data **":goto220
660 get a$:if a$=r$ then gosub1080:goto220
670 if a$=s$ then f=f+1:gosub1080
680 onfgoto630,660,630
REM Load/Save Data
690 print"{DOWN}{RVS} load data ":op=1:goto710
700 print"{DOWN}{RVS} save file ":op=0
710 in$=n$:input"{DOWN}filename{OS-4}";in$:if in$=n$ then220
720 f=0:print"{DOWN}{BLK}{RVS}t{OFF}ape or {RVS}d{OFF}isk: W";
730 get a$:if a$="t"then print"t{DOWN}":goto880
740 if a$<>"d"then730
750 print"d{DOWN}":open15,8,15,"i0:":b=ea-sa:in$="0:"+in$:if op then810
760 open 1,8,8,in$+",p,w":gosub860:if a then220
770 ah=int(sa/256):al=sa-(ah*256):print#1,chr$(al);chr$(ah);
780 for i=0 to b:print#1,chr$(peek(bs+i));:if st then800
790 next:close1:close15:goto940
800 gosub1060:print"{DOWN}{BLK}error during save:{OS-4}":gosub860:goto220
810 open 1,8,8,in$+",p,r":gosub860:if a then220
820 get#1,a$,b$:ad=asc(a$+z$)+256*asc(b$+z$):if ad<>sa then f=1:goto850
830 for i=0 to b:get#1,a$:poke bs+i,asc(a$+z$):if(i<>b)and st then f=2:ad=i:i=b
840 next:if st<>64 then f=3
850 close1:close15:on abs(f>0)+1 goto960,970
860 input#15,a,a$:if a then close1:close15:gosub1060:print"{RVS}error: "a$
870 return
880 poke183,peek(fa+2):poke187,peek(fa+3):poke188,peek(fa+4):ifop=0then920
890 sys 63466:if(peek(783)and1)then gosub1060:print"{DOWN}{RVS} file not found ":goto690
900 ad=peek(829)+256*peek(830):if ad<>sa then f=1:goto970
910 a=peek(831)+256*peek(832)-1:f=f-2*(a<ea)-3*(a>ea):ad=a-ad:goto930
920 a=sa:b=ea+1:gosub1010:poke780,3:sys 63338
930 a=bs:b=bs+(ea-sa)+1:gosub1010:on op goto950:sys 63591
940 gosub1080:print"{BLU}** save completed **":goto220
950 poke147,0:sys 63562:if st>0 then970
960 gosub1080:print"{BLU}** load completed **":goto220
970 gosub1060:print"{BLK}{RVS}error during load:{DOWN}{OS-4}":on f gosub980,990,1000:goto220
980 print"incorrect starting address (";:gosub360:print")":return
990 print"load ended at ";:ad=sa+ad:gosub360:print d$:return
1000 print"truncated at ending address":return
1010 ah=int(a/256):al=a-(ah*256):poke193,al:poke194,ah
1020 ah=int(b/256):al=b-(ah*256):poke174,al:poke175,ah:return
REM check validity of ending address, using ad as parameter
REM
1030 if ad<sa or ad>ea then1050
REM Check validity of starting address, using ad as parameter
REM f=0 is success
1040 if (ad>511 and ad<65280) then gosub1080: f=0: return
REM Error message. Gosub AngryBuzz, draw error, set error flag, return
1050 gosub1060:print"{RVS} invalid address {DOWN}{BLK}":f=1:return
REM AngryBuzz
1060 poke sd+5,31:poke sd+6,208:poke sd,240:poke sd+1,4:poke sd+4,33
1070 for s=1 to 100:next:goto1090
1080 poke sd+5,8:poke sd+6,240:poke sd,0:poke sd+1,90:poke sd+4,17
1090 for s=1 to 100:next:poke sd+4,0:poke sd,0:poke sd+1,0:return