MLX II by Ottis Cowper Ver 1.1

From Public Wiki
Revision as of 03:29, 13 October 2021 by Legg (talk | contribs) (→‎Code)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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