From fd7ee3ed61fbb2e74120ade792f89b0698efb7fc Mon Sep 17 00:00:00 2001 From: dschmenk Date: Mon, 8 Aug 2016 15:41:10 -0700 Subject: [PATCH 01/58] Shift pin number over for proper addressing --- src/libsrc/portio.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsrc/portio.pla b/src/libsrc/portio.pla index 6f7efda..57088e6 100644 --- a/src/libsrc/portio.pla +++ b/src/libsrc/portio.pla @@ -32,7 +32,7 @@ export def portRead end def digitalWrite(pin, val) - return ^ANN0[pin&3+val&1] + return ^ANN0[((pin&3)<<1)+val&1] end export def portWrite(val) From 21b5c85d7a97716fc5df57e9871fd75db46b4afc Mon Sep 17 00:00:00 2001 From: Peter Ferrie Date: Sun, 22 Jan 2017 10:51:59 -0800 Subject: [PATCH 02/58] include header for uintptr_t --- src/toolsrc/codegen.c | 1 + src/toolsrc/lex.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index 78d93c2..1a6cf1b 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -1,3 +1,4 @@ +#include #include #include #include "tokens.h" diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index 36bb711..b62f999 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -8,6 +8,7 @@ * governing permissions and limitations under the License. */ +#include #include #include #include From 988645cf8d48cda26cbd8df37c782b1e4a5e2c00 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Sat, 28 Jan 2017 12:27:34 -0800 Subject: [PATCH 03/58] Save a few bytes, somehing I meant to do a long time ago... --- SANDBOX.PO | Bin 143360 -> 143360 bytes src/vmsrc/a1cmd.pla | 2 +- src/vmsrc/cmd.pla | 2 +- src/vmsrc/plvm01.s | 121 +++++++++++++++++++++++++------------------ src/vmsrc/plvm02.s | 121 +++++++++++++++++++++++++------------------ src/vmsrc/plvm03.s | 121 +++++++++++++++++++++++++------------------ src/vmsrc/soscmd.pla | 2 +- 7 files changed, 216 insertions(+), 153 deletions(-) mode change 100644 => 100755 SANDBOX.PO diff --git a/SANDBOX.PO b/SANDBOX.PO old mode 100644 new mode 100755 index be7c9a5c3a616b28b0fa2724c7fe92f0e6ab132a..e81dcd9799d7096ad9f8b6e014a7519c460457cd GIT binary patch delta 2457 zcmb7EeN0v78Gqly6|P*0@BIYfUOZ4lJiX#^RyUm=v=yZEklpH`0t&g3>kH*WnZY~i zvVa}9c4?d03q8bT302aSm_^O?bj#M}UbM@)rm2T;Kl#JbiGbN6nvJ+6ZSS7BP}s<-s$C{}Y7zKY_TA{1J(YM$S(vE4f{;X)77(A?n?I&zZ}@mxR=*U+VzU|m5P(~x>~QRfma({E7cmy z(;tb(Qh}v~?V5ekK6O8HA~iCpgZWsU90{vaBO26K!!@c_BP|6tHo3Xy#_ufZordPs zsiB3zJ7eHKH~*2Uotsa)KGL}P<*WY~yz?$NK4fmTqelTiSf zC)dP3JsK~Llix0?H|-(Kro+<@xNX`NxYgXj!NWf|Yz?%utj48*_Lj|Xj<%G+8DeK} zzNG*Mc%%Jg?^|A6;(9ogIk9diYw-5q=M$l!xuL&Y`0D%xA|WCT77Z(Vz4#CPYt8G) zcC$b_Et?6oY$L;#o#c#VFPXFKBX8J`keIEGcV`wBita**< zhcKchK0n2zDQ#-LTpx|+!c zl`oFrF}zm!6~zT0en)XJh?%suOmP`#&Nlqr>?&(V7I7n9-l{aW;o`?v^h$ZFwNzSz z+{o+aC`S=@I*UMLIVYQxx7+Y;Y*IdJ!&TYqtR1T%-vId)?YQ`B-3WT)BRZ=;_=pbm zmCNmTZNAAW84zlsTobQlG;o+g%N%*ms?4_I`kL$3w5B_);DrADRuN9kq1)^Lt=u4A zw^C02S=y8jCa)wTiu?u&XSq>6r2OPXT;S?+_%mrHFXbWOOy6Tf*eiEhL~svVM42kr zUc^6l9)jXK+{h>&v$1=lebQMF1vBFW)F1vT}aj^GS;42&*y$%*ipE-$|YRB3gucD90c?+GeHx!w$TD2Shrk1L_#$ z8)lI@{1$4V1`Y&AEp9~Qi#E8I0o6*2sWb|>q(lCvL#gk?9{g+Nold+ZuQN~d{1nj= z=-o>5S+)g&Ov=4ZTmhqVb>TcSJiQrFLX8G$K+&gr%yonq#MY4QCaB5&s)Id+b`U=30fs|6gJD9 zO6_r6xE)IRYT%Z=HJ(C5pA`t_6~3wj<_b@+>8|($tFOk;RfBfspj?56++QBY!YY^` z%>CozxE$Y5{(c-E1hM}FE)t7S4n;l=O7XQ)E^x@l3E0phQq<(Rm12UCH3Oqw;F^5N zsqFtgb_r};5bI^3x>@w;tac|ts0T5=xEn%9$d}J4GbeEQVLe{{(g|5<#`SVOPC5b2 zU?1J76q|I0-0c!+hSUg!-2)u_L3vJR29kT75a<=8N_Pg|>b`fcvb0oM4}tO}rMU+? zi=hD|unzJmvzP{5hy@JXPj8ZPz6TfLr1D-5-rf&;1q)u5L4ZqQN1nM=+JKk0bOueP7O^6`uBwi&K2TM)vs5R=pKbEZv>_dWQMXd!0+mP@Ai(D)aJsXj*X~p%X z>zL>%0MhJPqi25Ul(!U#9wSQsNQki9QX#5XRdwJ%8WI>7S_a3HjVibwJohzw%RV4L eXQlx-;rH^K1)hNsy*7o81kJ`z@jJcv{eJ_OJ$Y6D delta 2354 zcmb7DeQZcV4fGXgBhTA*q4Kn}c2`GCws?n}rQSpl!0 zc7!fzr);fCop8q{O&O~w*+d%_4BEO1JJl*mr`0C5V@KLXLWx3|Akr2Mqz&)9XLn1d z{jpirz3-ggxxe$f_ngyvBd_;H-e{|q)-5MPA9AKO}J-xHr|6dOB5`V#)K#iR53BA0}@mEh$aPo;sHLe(FwY>s0qt|I|FWA77bx zDKVJ%Jdr>7+2r3Q`zC)pd3o}a$(6|sNhx_~tZL5*?f)qv{6C4foGO^wI@LaP0!6G# z>`0tXe3IBW+3?>)lqG|q!Xx3Ka4>QtIuxA~=SeWUX(5D;=t3mx2rVm%d^sp^s9sny z_x3GuKJZTc>g9JPW^V+ebm^SqP9RplZTW+V9XCdABbVbrU`<2i_6)5_Wi@@l8m?3A zx~$!ID;WAX@6BZw!-LUbG8n#{cWyq{94?D~FY+Lh>1PeDY|c*`N*`A_L#Bu+Y>Lk3 zjHHLc8MW7f;h|74Iuuc^5~>bHsxflR*68MP<}y6H_L`r_e3GjXZg%0qU;A#I3x-Zk ztMGsLt_CAnATYRh2h0Vgn^xryBlF2w1)5bI0n5H8Tdl!JJQ^{Nr00f0+3fLfWM1`t zK0^NG4aZU5Ld3&8*GsPpv%ydtAAcdL*upqXEVk({g^z-Z;)OHxQebpnAIk7H+c-yg zU{CV~C=W!NjRDrI$FH9^JE43m+FS&$cu#p@we4Yl&d4MExqUbLrbn*yf7U;9=HZXd zP?1par}np4r5E1cxkucR8oHhSK)mo6B0(t{?MUNpTx zM|DT(jINjNHoQuC!w;y>@D{Bw{E*(a4AWiqb5s-9esm{0vL9^RNnOCxVP&KHVdJG1 z0FKS<2m2`>ybIUadp_8T+n;@KJMX$7l6xV?ah?6)c^HOG>^m|P;dWYv65QU;SP2=N zX#GQmuP&=FwC7ScaY(yaMJtr7$=X%YZbPZKlDLW2&&ixjxMR5#BVC-tvsYT-YrwNm zD{NQJFU9j(JioFHO1`l3(B8brR`{P^WFtR&vkg`i@&-{$NTbX(IwG2S4rEN3FKLV{ z+y-^k(}s+tf(8UJ|4$48uJ_EU&xF!kT4~xKbJE$2s}NmYQ6e(&Yh_$rd6J(sAAlko zGy8Mo9EWHj{D~J=P`*+c&@5u4IO|1s~^eB-6T)yGb;Bc+r(FKa~5(}_!s0Yp{$x9>EyqZ+Y(^ffG@}z_vtKXkWi5vrC+ppWO5;YnmzLCsbLor< zyrfyOSXfyHc;F-US_f>j3|IuucZs|jbGOKa%4t0Y@$AzMSdXQ9*Z~$DKD~~}RL;}N zMozX$zh}-)coO`qsS`?yGN}IFs0B%!vR*pNPIZDEnpm(CR>J^GcEWbJ$n0HU#irWQ z1*OaJSy6uGS=+n7X~Ua%^h)t+j7srT1fQN$Uz(lo!X_POSG%BAkC5+Ke%{DOszg2E zH%J5Qv2G|XLrPyY-sW(%rIHYpah%2yHd>jwj9)UD^{*=a5X-N%`!`M;M zH7k2|3)pz2C>ZHg0#&!*Q+wB)yh3`2(iQIdD}*nUM%f1k!PTV3OI916%JkJ?&c}%d zF%?doJDpbQsgVW{*N6>B?C$08kMx{cej+27(TJD%d=SifUK^$|O3r4>MrsLzr7Yk@xkSh1}JVBhRbV^a%v{d?|Uf|a& zC27MPXh{8f!C9ih(wtGcoAD53{y=<}v=vbCb>b|bQjJZD82H+Xr9^rM+ohK9&s5~A z$i8C1^EBZ-S@VEVIF32_Zz!R;h&@X9$FtabHo;SfJ&`qc*#*y1;(SU?FW`jY;5pqH xtt(V{iV!8_D;b4~*bh*PQMnGP;(sk^3^@Es1J|a>UXuA;E`I?+aP~0#=AU(ZV#ojh diff --git a/src/vmsrc/a1cmd.pla b/src/vmsrc/a1cmd.pla index 2c90ca4..2fc191e 100644 --- a/src/vmsrc/a1cmd.pla +++ b/src/vmsrc/a1cmd.pla @@ -39,7 +39,7 @@ predef loadmod, execmod, lookupstrmod // // System variables. // -word version = $0092 // 00.92 +word version = $0094 // 00.94 word systemflags = 0 word heap word symtbl, lastsym diff --git a/src/vmsrc/cmd.pla b/src/vmsrc/cmd.pla index 89b1969..8ed47a6 100644 --- a/src/vmsrc/cmd.pla +++ b/src/vmsrc/cmd.pla @@ -33,7 +33,7 @@ predef loadmod, execmod, lookupstrmod // // System variable. // -word version = $0093 // 00.93 +word version = $0094 // 00.94 word systemflags = 0 word heap word xheap = $0800 diff --git a/src/vmsrc/plvm01.s b/src/vmsrc/plvm01.s index 31c685f..dcd4f12 100644 --- a/src/vmsrc/plvm01.s +++ b/src/vmsrc/plvm01.s @@ -77,9 +77,10 @@ MULLP LSR TMPH ; MULTPLRH DEY BNE MULLP STA ESTKH+1,X ; PRODH - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCREMENT TOS ;* @@ -210,8 +211,9 @@ ADD LDA ESTKL,X LDA ESTKH,X ADC ESTKH+1,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SUB TOS FROM TOS-1 ;* @@ -222,8 +224,9 @@ SUB LDA ESTKL+1,X LDA ESTKH+1,X SBC ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ; ;* ;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 @@ -237,8 +240,9 @@ IDXW LDA ESTKL,X LDA ESTKH,X ADC ESTKH+1,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* BITWISE AND TOS TO TOS-1 ;* @@ -248,8 +252,9 @@ BAND LDA ESTKL+1,X LDA ESTKH+1,X AND ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCLUSIVE OR TOS TO TOS-1 ;* @@ -259,8 +264,9 @@ IOR LDA ESTKL+1,X LDA ESTKH+1,X ORA ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* EXLUSIVE OR TOS TO TOS-1 ;* @@ -270,8 +276,9 @@ XOR LDA ESTKL+1,X LDA ESTKH+1,X EOR ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 LEFT BY TOS ;* @@ -290,9 +297,10 @@ SHL2 ASL ESTKL+1,X ROL ESTKH+1,X DEY BNE SHL2 -SHL3 INX - LDY IPY - JMP NEXTOP +SHL3 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 RIGHT BY TOS ;* @@ -318,9 +326,10 @@ SHR3 CMP #$80 DEY BNE SHR3 STA ESTKH+1,X -SHR4 INX - LDY IPY - JMP NEXTOP +SHR4 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* LOGICAL NOT ;* @@ -344,8 +353,9 @@ LAND LDA ESTKL+1,X LDA #$FF LAND1 STA ESTKL+1,X STA ESTKH+1,X -LAND2 INX - JMP NEXTOP +;LAND2 INX +; JMP NEXTOP +LAND2 JMP DROP ;* ;* LOGICAL OR ;* @@ -357,8 +367,9 @@ LOR LDA ESTKL,X LDA #$FF STA ESTKL+1,X STA ESTKH+1,X -LOR1 INX - JMP NEXTOP +;LOR1 INX +; JMP NEXTOP +LOR1 JMP DROP ;* ;* DUPLICATE TOS ;* @@ -375,8 +386,9 @@ PUSH LDA ESTKL,X PHA LDA ESTKH,X PHA - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* PULL FROM CALL STACK TO EVAL STACK ;* @@ -541,10 +553,11 @@ SB LDA ESTKL+1,X STY IPY LDY #$00 STA (TMP),Y - INX - INX LDY IPY - JMP NEXTOP + INX +; INX +; JMP NEXTOP + JMP DROP SW LDA ESTKL+1,X STA TMPL LDA ESTKH+1,X @@ -556,10 +569,11 @@ SW LDA ESTKL+1,X INY LDA ESTKH,X STA (TMP),Y - INX - INX LDY IPY - JMP NEXTOP + INX +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET ;* @@ -569,9 +583,10 @@ SLB +INC_IP TAY LDA ESTKL,X STA (IFP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP SLW +INC_IP LDA (IP),Y STY IPY @@ -581,9 +596,10 @@ SLW +INC_IP INY LDA ESTKH,X STA (IFP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK ;* @@ -619,9 +635,10 @@ SAB +INC_IP STY IPY LDY #$00 STA (TMP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP SAW +INC_IP LDA (IP),Y STA TMPL @@ -635,9 +652,10 @@ SAW +INC_IP INY LDA ESTKH,X STA (TMP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK ;* @@ -678,10 +696,11 @@ ISEQ LDA ESTKL,X CMP ESTKH+1,X BNE ISFLS ISTRU LDA #$FF - INX - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ISNE LDA ESTKL,X CMP ESTKL+1,X @@ -690,10 +709,11 @@ ISNE LDA ESTKL,X CMP ESTKH+1,X BNE ISTRU ISFLS LDA #$00 - INX - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ISGE LDA ESTKL+1,X CMP ESTKL,X @@ -797,8 +817,9 @@ IBRNCH LDA IPL LDA IPH ADC ESTKH,X STA IPH - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) ;* diff --git a/src/vmsrc/plvm02.s b/src/vmsrc/plvm02.s index a4f567b..d021fc2 100644 --- a/src/vmsrc/plvm02.s +++ b/src/vmsrc/plvm02.s @@ -404,8 +404,9 @@ ADD LDA ESTKL,X LDA ESTKH,X ADC ESTKH+1,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SUB TOS FROM TOS-1 ;* @@ -416,8 +417,9 @@ SUB LDA ESTKL+1,X LDA ESTKH+1,X SBC ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 ;* @@ -430,8 +432,9 @@ IDXW LDA ESTKL,X LDA ESTKH,X ADC ESTKH+1,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* MUL TOS-1 BY TOS ;* @@ -460,9 +463,10 @@ MULLP LSR TMPH ; MULTPLRH DEY BNE MULLP STA ESTKH+1,X ; PRODH - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* INTERNAL DIVIDE ALGORITHM ;* @@ -580,8 +584,9 @@ BAND LDA ESTKL+1,X LDA ESTKH+1,X AND ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCLUSIVE OR TOS TO TOS-1 ;* @@ -591,8 +596,9 @@ IOR LDA ESTKL+1,X LDA ESTKH+1,X ORA ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* EXLUSIVE OR TOS TO TOS-1 ;* @@ -602,8 +608,9 @@ XOR LDA ESTKL+1,X LDA ESTKH+1,X EOR ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 LEFT BY TOS ;* @@ -622,9 +629,10 @@ SHL2 ASL ESTKL+1,X ROL ESTKH+1,X DEY BNE SHL2 -SHL3 INX - LDY IPY - JMP NEXTOP +SHL3 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 RIGHT BY TOS ;* @@ -650,9 +658,10 @@ SHR3 CMP #$80 DEY BNE SHR3 STA ESTKH+1,X -SHR4 INX - LDY IPY - JMP NEXTOP +SHR4 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* LOGICAL NOT ;* @@ -676,8 +685,9 @@ LAND LDA ESTKL+1,X LDA #$FF LAND1 STA ESTKL+1,X STA ESTKH+1,X -LAND2 INX - JMP NEXTOP +;LAND2 INX +; JMP NEXTOP +LAND2 JMP DROP ;* ;* LOGICAL OR ;* @@ -689,8 +699,9 @@ LOR LDA ESTKL,X LDA #$FF STA ESTKL+1,X STA ESTKH+1,X -LOR1 INX - JMP NEXTOP +;LOR1 INX +; JMP NEXTOP +LOR1 JMP DROP ;* ;* DUPLICATE TOS ;* @@ -707,8 +718,9 @@ PUSH LDA ESTKL,X PHA LDA ESTKH,X PHA - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* PULL FROM CALL STACK TO EVAL STACK ;* @@ -996,10 +1008,11 @@ SB LDA ESTKL+1,X STY IPY LDY #$00 STA (TMP),Y - INX - INX LDY IPY - JMP NEXTOP + INX +; INX +; JMP NEXTOP + JMP DROP SW LDA ESTKL+1,X STA TMPL LDA ESTKH+1,X @@ -1011,10 +1024,11 @@ SW LDA ESTKL+1,X INY LDA ESTKH,X STA (TMP),Y - INX - INX LDY IPY - JMP NEXTOP + INX +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET ;* @@ -1024,9 +1038,10 @@ SLB +INC_IP TAY LDA ESTKL,X STA (IFP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP SLW +INC_IP LDA (IP),Y STY IPY @@ -1036,9 +1051,10 @@ SLW +INC_IP INY LDA ESTKH,X STA (IFP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK ;* @@ -1074,9 +1090,10 @@ SAB +INC_IP STY IPY LDY #$00 STA (TMP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP SAW +INC_IP LDA (IP),Y STA TMPL @@ -1090,9 +1107,10 @@ SAW +INC_IP INY LDA ESTKH,X STA (TMP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK ;* @@ -1133,10 +1151,11 @@ ISEQ LDA ESTKL,X CMP ESTKH+1,X BNE ISFLS ISTRU LDA #$FF - INX - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ISNE LDA ESTKL,X CMP ESTKL+1,X @@ -1145,10 +1164,11 @@ ISNE LDA ESTKL,X CMP ESTKH+1,X BNE ISTRU ISFLS LDA #$00 - INX - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ISGE LDA ESTKL+1,X CMP ESTKL,X @@ -1252,8 +1272,9 @@ IBRNCH LDA IPL LDA IPH ADC ESTKH,X STA IPH - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) ;* diff --git a/src/vmsrc/plvm03.s b/src/vmsrc/plvm03.s index bdd3425..8afbd71 100644 --- a/src/vmsrc/plvm03.s +++ b/src/vmsrc/plvm03.s @@ -250,9 +250,10 @@ MULLP LSR TMPH ; MULTPLRH DEY BNE MULLP STA ESTKH+1,X ; PRODH - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* NEGATE TOS ;* @@ -292,8 +293,9 @@ ADD LDA ESTKL,X LDA ESTKH,X ADC ESTKH+1,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SUB TOS FROM TOS-1 ;* @@ -304,8 +306,9 @@ SUB LDA ESTKL+1,X LDA ESTKH+1,X SBC ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ; ;* ;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 @@ -319,8 +322,9 @@ IDXW LDA ESTKL,X LDA ESTKH,X ADC ESTKH+1,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCREMENT TOS ;* @@ -355,8 +359,9 @@ BAND LDA ESTKL+1,X LDA ESTKH+1,X AND ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCLUSIVE OR TOS TO TOS-1 ;* @@ -366,8 +371,9 @@ IOR LDA ESTKL+1,X LDA ESTKH+1,X ORA ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* EXLUSIVE OR TOS TO TOS-1 ;* @@ -377,8 +383,9 @@ XOR LDA ESTKL+1,X LDA ESTKH+1,X EOR ESTKH,X STA ESTKH+1,X - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 LEFT BY TOS ;* @@ -397,9 +404,10 @@ SHL2 ASL ESTKL+1,X ROL ESTKH+1,X DEY BNE SHL2 -SHL3 INX - LDY IPY - JMP NEXTOP +SHL3 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 RIGHT BY TOS ;* @@ -425,9 +433,10 @@ SHR3 CMP #$80 DEY BNE SHR3 STA ESTKH+1,X -SHR4 INX - LDY IPY - JMP NEXTOP +SHR4 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* LOGICAL NOT ;* @@ -451,8 +460,9 @@ LAND LDA ESTKL+1,X LDA #$FF LAND1 STA ESTKL+1,X STA ESTKH+1,X -LAND2 INX - JMP NEXTOP +;LAND2 INX +; JMP NEXTOP +LAND2 JMP DROP ;* ;* LOGICAL OR ;* @@ -464,8 +474,9 @@ LOR LDA ESTKL,X LDA #$FF STA ESTKL+1,X STA ESTKH+1,X -LOR1 INX - JMP NEXTOP +;LOR1 INX +; JMP NEXTOP +LOR1 JMP DROP ;* ;* DUPLICATE TOS ;* @@ -482,8 +493,9 @@ PUSH LDA ESTKL,X PHA LDA ESTKH,X PHA - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* PULL FROM CALL STACK TO EVAL STACK ;* @@ -663,10 +675,11 @@ SB LDA ESTKL+1,X STY IPY LDY #$00 STA (TMP),Y - INX - INX LDY IPY - JMP NEXTOP + INX +; INX +; JMP NEXTOP + JMP DROP SW LDA ESTKL+1,X STA TMPL LDA ESTKH+1,X @@ -678,10 +691,11 @@ SW LDA ESTKL+1,X INY LDA ESTKH,X STA (TMP),Y - INX - INX LDY IPY - JMP NEXTOP + INX +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET ;* @@ -691,9 +705,10 @@ SLB +INC_IP TAY LDA ESTKL,X STA (IFP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP SLW +INC_IP LDA (IP),Y STY IPY @@ -703,9 +718,10 @@ SLW +INC_IP INY LDA ESTKH,X STA (IFP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK ;* @@ -741,9 +757,10 @@ SAB +INC_IP STY IPY LDY #$00 STA (TMP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP SAW +INC_IP LDA (IP),Y STA TMPL @@ -757,9 +774,10 @@ SAW +INC_IP INY LDA ESTKH,X STA (TMP),Y - INX LDY IPY - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK ;* @@ -800,10 +818,11 @@ ISEQ LDA ESTKL,X CMP ESTKH+1,X BNE ISFLS ISTRU LDA #$FF - INX - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ISNE LDA ESTKL,X CMP ESTKL+1,X @@ -812,10 +831,11 @@ ISNE LDA ESTKL,X CMP ESTKH+1,X BNE ISTRU ISFLS LDA #$00 - INX - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ISGE LDA ESTKL+1,X CMP ESTKL,X @@ -919,8 +939,9 @@ IBRNCH LDA IPL LDA IPH ADC ESTKH,X STA IPH - INX - JMP NEXTOP +; INX +; JMP NEXTOP + JMP DROP ;* ;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) ;* diff --git a/src/vmsrc/soscmd.pla b/src/vmsrc/soscmd.pla index 22aa240..1fac784 100644 --- a/src/vmsrc/soscmd.pla +++ b/src/vmsrc/soscmd.pla @@ -34,7 +34,7 @@ predef loadmod, execmod, lookupstrmod // // System variables. // -word version = $0092 // 00.92 +word version = $0094 // 00.94 word systemflags = 0 byte refcons = 0 byte devcons = 0 From 73559b7f0b63f7ca415910b99deb496e2f69ce5e Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 12 Feb 2017 19:03:46 -0800 Subject: [PATCH 04/58] Remove useless type casts --- src/toolsrc/codegen.c | 2 +- src/toolsrc/lex.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index 1a6cf1b..aa005c2 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -468,7 +468,7 @@ int emit_data(int vartype, int consttype, long constval, int constsize) else if (consttype & STRING_TYPE) { datasize = constsize; - str = (char *)(uintptr_t)constval; + str = (char *)constval; printf("\t%s\t$%02X\n", DB, --constsize); while (constsize-- > 0) { diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index b62f999..36d0b14 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -11,8 +11,8 @@ #include #include #include -#include #include +#include #include "tokens.h" #include "symbols.h" @@ -230,7 +230,7 @@ t_token scan(void) * String constant. */ scantoken = STRING_TOKEN; - constval = (long)(uintptr_t)(++scanpos); + constval = (long)++scanpos; while (*scanpos && *scanpos != '\"') { if (*scanpos == '\\') @@ -472,7 +472,7 @@ int next_line(void) outer_filename = filename; outer_lineno = lineno; new_filename = (char*) malloc(tokenlen-1); - strncpy(new_filename, (char*)(uintptr_t)constval, tokenlen-2); + strncpy(new_filename, (char*)constval, tokenlen-2); new_filename[tokenlen-2] = 0; inputfile = fopen(new_filename, "r"); if (inputfile == NULL) { From 8ed9c9868d48f94be79a42dc3a9cb4790326f954 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 12 Feb 2017 19:35:33 -0800 Subject: [PATCH 05/58] Tab vs spaces cleanup --- src/toolsrc/codegen.c | 16 ++++++++-------- src/toolsrc/lex.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index aa005c2..0c1e299 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -8,7 +8,7 @@ /* * Symbol table and fixup information. */ -#define ID_LEN 32 +#define ID_LEN 32 static int consts = 0; static int externs = 0; static int globals = 0; @@ -30,8 +30,8 @@ static int idlocal_offset[128]; static char fixup_size[2048]; static int fixup_type[2048]; static int fixup_tag[2048]; -#define FIXUP_BYTE 0x00 -#define FIXUP_WORD 0x80 +#define FIXUP_BYTE 0x00 +#define FIXUP_WORD 0x80 int id_match(char *name, int len, char *id) { if (len == id[0]) @@ -148,13 +148,13 @@ int idglobal_add(char *name, int len, int type, int size) if (!(type & EXTERN_TYPE)) { emit_idglobal(globals, size, name); - idglobal_tag[globals] = globals; - globals++; + idglobal_tag[globals] = globals; + globals++; } else { printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals][1], externs); - idglobal_tag[globals++] = externs++; + idglobal_tag[globals++] = externs++; } return (1); } @@ -255,8 +255,8 @@ int fixup_new(int tag, int type, int size) /* * Emit assembly code. */ -#define BYTECODE_SEG 8 -#define INIT 16 +#define BYTECODE_SEG 8 +#define INIT 16 #define SYSFLAGS 32 static int outflags = 0; static const char *DB = ".BYTE"; diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index 36d0b14..f2294cb 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -38,31 +38,31 @@ t_token keywords[] = { DEFAULT_TOKEN, 'O', 'T', 'H', 'E', 'R', 'W', 'I', 'S', 'E', ENDCASE_TOKEN, 'W', 'E', 'N', 'D', FOR_TOKEN, 'F', 'O', 'R', - TO_TOKEN, 'T', 'O', - DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O', - STEP_TOKEN, 'S', 'T', 'E', 'P', + TO_TOKEN, 'T', 'O', + DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O', + STEP_TOKEN, 'S', 'T', 'E', 'P', NEXT_TOKEN, 'N', 'E', 'X', 'T', REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T', - UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L', - BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K', - CONTINUE_TOKEN, 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'E', - ASM_TOKEN, 'A', 'S', 'M', - DEF_TOKEN, 'D', 'E', 'F', - EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T', - IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T', + UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L', + BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K', + CONTINUE_TOKEN, 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'E', + ASM_TOKEN, 'A', 'S', 'M', + DEF_TOKEN, 'D', 'E', 'F', + EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T', + IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T', INCLUDE_TOKEN, 'I', 'N', 'C', 'L', 'U', 'D', 'E', RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N', END_TOKEN, 'E', 'N', 'D', - DONE_TOKEN, 'D', 'O', 'N', 'E', + DONE_TOKEN, 'D', 'O', 'N', 'E', LOGIC_NOT_TOKEN, 'N', 'O', 'T', LOGIC_AND_TOKEN, 'A', 'N', 'D', - LOGIC_OR_TOKEN, 'O', 'R', + LOGIC_OR_TOKEN, 'O', 'R', BYTE_TOKEN, 'B', 'Y', 'T', 'E', - WORD_TOKEN, 'W', 'O', 'R', 'D', + WORD_TOKEN, 'W', 'O', 'R', 'D', CONST_TOKEN, 'C', 'O', 'N', 'S', 'T', STRUC_TOKEN, 'S', 'T', 'R', 'U', 'C', PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F', - SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S', + SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S', EOL_TOKEN }; @@ -104,8 +104,8 @@ t_token scan(void) else if (*scanpos == '\0' || *scanpos == '\n' || *scanpos == ';') scantoken = EOL_TOKEN; else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z') - || (scanpos[0] >= 'A' && scanpos[0] <= 'Z') - || (scanpos[0] == '_')) + || (scanpos[0] >= 'A' && scanpos[0] <= 'Z') + || (scanpos[0] == '_')) { /* * ID, either variable name or reserved word. @@ -117,9 +117,9 @@ t_token scan(void) scanpos++; } while ((*scanpos >= 'a' && *scanpos <= 'z') - || (*scanpos >= 'A' && *scanpos <= 'Z') - || (*scanpos == '_') - || (*scanpos >= '0' && *scanpos <= '9')); + || (*scanpos >= 'A' && *scanpos <= 'Z') + || (*scanpos == '_') + || (*scanpos >= '0' && *scanpos <= '9')); scantoken = ID_TOKEN; tokenlen = scanpos - tokenstr; /* @@ -402,7 +402,7 @@ int scan_lookahead(void) char *backpos = scanpos; char *backstr = tokenstr; int prevtoken = scantoken; - int prevlen = tokenlen; + int prevlen = tokenlen; int look = scan(); scanpos = backpos; tokenstr = backstr; From 3e8aaa8325759a47f30b92cbef31b6fd63478ee8 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 11 Mar 2017 20:27:53 -0800 Subject: [PATCH 06/58] Instructions for Rogue --- doc/Rogue Instructions.rtf | 178 +++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100755 doc/Rogue Instructions.rtf diff --git a/doc/Rogue Instructions.rtf b/doc/Rogue Instructions.rtf new file mode 100755 index 0000000..161d81f --- /dev/null +++ b/doc/Rogue Instructions.rtf @@ -0,0 +1,178 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160 +{\fonttbl\f0\froman\fcharset0 TimesNewRomanPSMT;\f1\fmodern\fcharset0 Courier;\f2\fswiss\fcharset0 Helvetica; +} +{\colortbl;\red255\green255\blue255;} +{\info +{\author David Schmenk}}\margl1440\margr1440\vieww12540\viewh16140\viewkind1 +\deftab720 +\pard\pardeftab720\qc + +\f0\b\fs36 \cf0 \expnd0\expndtw0\kerning0 +PLASMA goes ROGUE\ +\pard\pardeftab720 + +\fs28 \cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Introduction\ +\pard\pardeftab720 + +\b0\fs24 \cf0 \expnd0\expndtw0\kerning0 +\ulnone This version of ROGUE is somewhat different than others. It is very simple in most ways, but I have developed a (I think) unique visibility algorithm that runs extremely fast. Fast enough to run interpreted by the PLASMA VM on a 1 MHz 6502, and space efficient enough to allow for large (in the future) dungeons. The unique feature of this ROGUE is that lighting becomes critical and strategic. You are in dark catacombs, after all. You enter with a lit lamp, throwing off a circle of light. There are also torches throughout the catacombs that light up a small surrounding circle of light. Other items in the catacombs are mana (health+energy increase), a key, a raft, and gold. You will also encounter a number of enemies that will track you down to try and kill you. You will also encounter doors, locked doors, windows, water, and crevasses.\ +\ +\pard\pardeftab720 + +\b\fs28 \cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Strategy\ +\pard\pardeftab720 + +\b0\fs24 \cf0 \expnd0\expndtw0\kerning0 +\ulnone As you travel through the catacombs, you must watch your health, energy, and lamp oil levels. Once health reaches zero, you are dead. As energy reaches zero, your vision will narrow and you will no longer be able to run. When the lamp oil runs out, you will be cast into darkness. If you see any torches in your field of vision, you can navigate to them. Taking the torch will extinguish the torch and replenish some of your lamp oil. Note that as you travel through the catacombs, your map of what you have seen will automatically fill in. But, if you are in the dark, you cannot read your map. You must turn on your lamp or get next to a torch before you can read the map again. If you are in the dark and can\'92t see any torches in your field of vision, you are in complete darkness. It is easy to lose your bearings. As such, the absolute direction movements no longer work (NSEW) - you will end up in a random direction if you try. However, the relative turns, left/right and forward/backward controls continue to work ( +\b \expnd0\expndtw0\kerning0 +that +\b0 \expnd0\expndtw0\kerning0 + you can do in the dark).\ +\ +Being in the dark can be advantageous, however. All the enemies in the catacombs can see you if you are in light, just as you can see them. If you are in darkness, they can't see you, and you can move around without being tracked. Don't run into them! Also, don't fall off a crevasse. You will hear certain noises giving you feedback on what is going on. A simple beep when you run into walls. A groan when an enemy moves towards you. A bleep when you pick an item up. Other noises when you fall over an edge or win a battle. These can be used strategically when moving in the dark.\ +\ +Health will slowly improve as you move around. However, energy is depleted as you move. Mana will increase both health and energy. If health is already at 100, it won\'92t go any higher. Same for energy, but it is important to keep both high. When energy goes low, you can no longer move quickly and your field-of-vision narrows. When health goes to zero, you are dead.\ +\ +\pard\pardeftab720 + +\b\fs28 \cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Tile Description\ +\pard\pardeftab720 + +\b0\fs24 \cf0 \expnd0\expndtw0\kerning0 +\ulnone As ROGUE uses the text screen for display, a little creativity is required to interpret the map. These are the characters you will see and what the represent. Once you get the hang of it, it will be just like looking at the unencoded Matrix.\ +\ +\pard\pardeftab720 + +\f1 \cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Screen Character\expnd0\expndtw0\kerning0 +\ulnone \'a0 \'a0 \'a0\expnd0\expndtw0\kerning0 +\ul Represents\ +\pard\pardeftab720 +\cf0 \expnd0\expndtw0\kerning0 +\ulnone \'a0\'a0\'a0# \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Wall\ +\'a0\'a0\'a0. \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Floor\ +\'a0\'a0\'a0: \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Window (barred opening)\ +\'a0 \'a0+ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Door\ +\'a0 \'a0% \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Locked Door (need key to open)\ +\'a0\'a0\'a0' ' space \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Crevasse (pit - don't fall in)\ +\'a0\'a0\'a0= \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Exit\ +\'a0\'a0\'a0- \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Entrance\ +\'a0\'a0\'a0* \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Torch\ +\'a0\'a0\'a0& \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Mana\ +\'a0\'a0\'a0, \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Key (yep, hard to spot)\ +\'a0 \'a0@ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Raft (need to cross water)\ + <<< Water\ +\'a0 \'a0>>> \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Water (you will drown without raft)\ +\'a0\'a0\'a0$ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Gold\ +\ +\pard\pardeftab720 +\cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Flashing\expnd0\expndtw0\kerning0 +\ulnone \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \expnd0\expndtw0\kerning0 +\ul Entity\ +\pard\pardeftab720 +\cf0 \expnd0\expndtw0\kerning0 +\ulnone \'a0\'a0\'a0T \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Thief\ +\'a0\'a0\'a0O \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Ogre\ +\'a0\'a0\'a0Z \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Zombie\ +\'a0\'a0\'a0R \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Rogue\ +\ +\'a0\expnd0\expndtw0\kerning0 +\ul Player\expnd0\expndtw0\kerning0 +\ulnone \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \expnd0\expndtw0\kerning0 +\ul Facing Direction\expnd0\expndtw0\kerning0 +\ulnone \ +\'a0\'a0\'a0^ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0North\ +\'a0\'a0\'a0\\ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0NE\ +\'a0\'a0\'a0> \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0East\ +\'a0\'a0\'a0/ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0SE\ +\'a0\'a0\'a0v \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0South\ +\'a0\'a0\'a0\\ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0SW\ +\'a0\'a0\'a0< \'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0\'a0West\ +\'a0\'a0\'a0/ \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0NW\ +\ +\pard\pardeftab720 + +\f0 \cf0 \expnd0\expndtw0\kerning0 +Tiles in light are inverse. Entities are displayed only when lit and in field of view. The map is only visible when lit, i.e lamp is on or standing next to a torch.\ +\ +\pard\pardeftab720 + +\b\fs28 \cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Interaction\ +\pard\pardeftab720 + +\f1\b0\fs24 \cf0 \expnd0\expndtw0\kerning0 +\ulc0 Keyboard commands\expnd0\expndtw0\kerning0 +\ulnone \'a0\'a0\'a0\'a0 \expnd0\expndtw0\kerning0 +\ul Action\ +\pard\pardeftab720 +\cf0 \expnd0\expndtw0\kerning0 +\ulnone \'a0\'a0\'a0Q \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Run (Quick)\ +\'a0\'a0\'a0W up-arrow \'a0 \'a0 \'a0 \'a0 \'a0 Forward\ +\'a0\'a0\'a0S down-arrow \'a0 \'a0 \'a0 \'a0 Backward\ +\'a0\'a0\'a0A left-arrow \'a0 \'a0 \'a0 \'a0 Turn left\ +\'a0\'a0\'a0D right-arrow \'a0 \'a0 \'a0 Turn right\ +\'a0\'a0\'a0I \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Move N\ +\'a0\'a0\'a0J \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Move W\ +\'a0\'a0\'a0K \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Move E\ +\'a0\'a0\'a0M \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Move S\ +\'a0\'a0\'a0< , \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Turn lamp down\ +\'a0\'a0\'a0> . \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Turn lamp up/on\ +\'a0\'a0\'a0O \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Turn lamp off\ +\'a0\'a0\'a0Space-bar \'a0 \'a0 \'a0 \'a0 \'a0 \'a0Open door\ +\'a0\'a0\'a0Return \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Pick up item\ +\'a0\'a0\'a0X \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 \'a0 Exit (die)\ +\pard\pardeftab720 + +\f0 \cf0 \expnd0\expndtw0\kerning0 +\ +Whenever you and an enemy end up on the same tile, battle commences. As you win fights, your skill increases, improving your attack effectiveness. As you advance through the catacombs, the enemies become more powerful. You will need to replenish health and energy with mana. Don't forget, the alternative to fighting is stealth in the darkness. During battle, you have the option to run. If you have low energy, you won't get very far. Also, when fighting, you get turned around so you can't depend on the direction you were facing before fighting. Running ('Q'uick) will get you away from enemies but will use much more energy.\ +\ +If you should die, restart the game by typing:\ +\pard\pardeftab720 + +\f1 \cf0 \expnd0\expndtw0\kerning0 ++rogue +\f2 \ +\pard\pardeftab720 + +\f0 \cf0 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720 + +\b\fs28 \cf0 \expnd0\expndtw0\kerning0 +\ul \ulc0 Map Levels\ +\pard\pardeftab720 + +\b0\fs24 \cf0 \expnd0\expndtw0\kerning0 +\ulnone Level maps are up to 62x62 in size (plus a wall boundary for an effective 64x64 map size). They can be smaller than this. The game will end when it tries to load an non-existent level. Levels start at file name \'93LEVEL0\'93 and can go all the way to \'93LEVEL9\'93, but must be sequential.\ +\ +There are two levels included on the disk, and an empty level for you to use as a template.\'a0You\'a0can edit the map levels, and add your own. They are simple ASCII text files. The included sandbox editor can edit the maps right on the disk. type:\ +\ +\pard\pardeftab720 + +\f1 \cf0 \expnd0\expndtw0\kerning0 +-sandbox level.empty +\f2 \ +\pard\pardeftab720 + +\f0 \cf0 \expnd0\expndtw0\kerning0 +\ +after exiting from ROGUE. Make your changes and save it as LEVEL0" to "LEVEL9". The next free level is currently "LEVEL2". You may also edit an existing level:\ +\ +\pard\pardeftab720 + +\f1 \cf0 \expnd0\expndtw0\kerning0 +-sandbox level0 +\f2 \ +\pard\pardeftab720 + +\f0 \cf0 \expnd0\expndtw0\kerning0 +\ +for instance.\ +\ +} \ No newline at end of file From 88e083eb754d17745b889777a2d22e94db087a2e Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 19 Mar 2017 18:20:47 -0700 Subject: [PATCH 07/58] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 727aa35..de1d09d 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
# The PLASMA Programming Language -![Luc Viatour / www.Lucnix.be](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1280px-Plasma-lamp_2.jpg) +![Luc Viatour / www.Lucnix.be](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) image credit: Luc Viatour / www.Lucnix.be
From 5eac0ad53b0ecf7ce35c2da7cde51255f5ea4449 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 19 Mar 2017 18:22:56 -0700 Subject: [PATCH 08/58] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de1d09d..ddee160 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
# The PLASMA Programming Language -![Luc Viatour / www.Lucnix.be](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) +![Luc Viatour / www.Lucnix.be] https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg image credit: Luc Viatour / www.Lucnix.be
From d18a0369e271deea1ef252e89eef280bae56d00a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 19 Mar 2017 18:24:49 -0700 Subject: [PATCH 09/58] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddee160..de1d09d 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
# The PLASMA Programming Language -![Luc Viatour / www.Lucnix.be] https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg +![Luc Viatour / www.Lucnix.be](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) image credit: Luc Viatour / www.Lucnix.be
From c34cade3858217fea515164537a425fae64c2ee8 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 25 Mar 2017 08:45:03 -0700 Subject: [PATCH 10/58] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de1d09d..72c3923 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
# The PLASMA Programming Language -![Luc Viatour / www.Lucnix.be](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) +![Luc Viatour](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) image credit: Luc Viatour / www.Lucnix.be
From 372267967aef5f1c4a53da0acd9187fafc3d20be Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 25 Mar 2017 12:12:20 -0700 Subject: [PATCH 11/58] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 72c3923..541d358 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@
# The PLASMA Programming Language + ![Luc Viatour](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) image credit: Luc Viatour / www.Lucnix.be
From db079b551b69063f772e4fe0612de3f1cdd920c0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 25 Mar 2017 12:15:02 -0700 Subject: [PATCH 12/58] Why did markdown break so much with inline images? --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 541d358..4b8bf5e 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ -
# The PLASMA Programming Language - +
![Luc Viatour](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) image credit: Luc Viatour / www.Lucnix.be
From 5b6a8d6375aa9d228acbb08f9a0bc67b109f90a6 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 25 Mar 2017 12:16:42 -0700 Subject: [PATCH 13/58] It seems embedded HTML broke my inline images among other things --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b8bf5e..04ce9e4 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # The PLASMA Programming Language -
+ ![Luc Viatour](https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Plasma-lamp_2.jpg/1200px-Plasma-lamp_2.jpg) image credit: Luc Viatour / www.Lucnix.be -
+ PLASMA: **P**roto **L**anguage **A**s**S**e**M**bler for **A**pple From 18b082460fc46c0f9ed088309b47bf3101552fcc Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 26 Mar 2017 20:06:25 -0700 Subject: [PATCH 14/58] Check for existing string in pool before copying CS string from aux mem --- src/vmsrc/plvm02.s | 54 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/src/vmsrc/plvm02.s b/src/vmsrc/plvm02.s index d021fc2..668d4d7 100644 --- a/src/vmsrc/plvm02.s +++ b/src/vmsrc/plvm02.s @@ -15,10 +15,10 @@ PROMPT = $33 ;* PRODOS ;* PRODOS = $BF00 -DEVCNT = $BF31 ; GLOBAL PAGE DEVICE COUNT +DEVCNT = $BF31 ; GLOBAL PAGE DEVICE COUNT DEVLST = $BF32 ; GLOBAL PAGE DEVICE LIST -MACHID = $BF98 ; GLOBAL PAGE MACHINE ID BYTE -RAMSLOT = $BF26 ; SLOT 3, DRIVE 2 IS /RAM'S DRIVER VECTOR +MACHID = $BF98 ; GLOBAL PAGE MACHINE ID BYTE +RAMSLOT = $BF26 ; SLOT 3, DRIVE 2 IS /RAM'S DRIVER VECTOR NODEV = $BF10 ;* ;* HARDWARE ADDRESSES @@ -786,7 +786,47 @@ CSX DEX TAY ADC IPH STA IPH - LDA (IP),Y + LDA PPH ; SCAN POOL FOR STRING ALREADY THERE + STA TMPH + LDA PPL + STA TMPL +_CMPPSX LDA TMPH ; CHECK FOR END OF POOL + CMP IFPH + BCC _CMPSX ; CHECK FOR MATCHING STRING + BNE _CPYSX ; BEYOND END OF POOL, COPY STRING OVER + LDA TMPL + CMP IFPL + BCS _CPYSX ; AT OR BEYOND END OF POOL, COPY STRING OVER +_CMPSX STA ALTRDOFF + LDA (TMP),Y ; COMPARE STRINGS FROM AUX MEM TO STRINGS IN MAIN MEM + STA ALTRDON + CMP (IP),Y ; COMPARE STRING LENGTHS + BNE _CNXTSX1 + TAY +_CMPCSX STA ALTRDOFF + LDA (TMP),Y ; COMPARE STRING CHARS FROM END + STA ALTRDON + CMP (IP),Y + BNE _CNXTSX + DEY + BNE _CMPCSX + LDA TMPL ; MATCH - SAVE EXISTING ADDR ON ESTK AND MOVE ON + STA ESTKL,X + LDA TMPH + STA ESTKH,X + BNE _CEXSX +_CNXTSX LDY #$00 + STA ALTRDOFF + LDA (TMP),Y + STA ALTRDON +_CNXTSX1 SEC + ADC TMPL + STA TMPL + LDA #$00 + ADC TMPH + STA TMPH + BNE _CMPPSX +_CPYSX LDA (IP),Y ; COPY STRING FROM AUX TO MAIN MEM POOL TAY ; MAKE ROOM IN POOL AND SAVE ADDR ON ESTK EOR #$FF CLC @@ -797,13 +837,13 @@ CSX DEX ADC PPH STA PPH STA ESTKH,X ; COPY STRING FROM AUX MEM BYTECODE TO MAIN MEM POOL -- LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE +_CPYSX1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE STA (PP),Y ; ALTWR IS OFF, NO NEED TO CHANGE IT HERE DEY CPY #$FF - BNE - + BNE _CPYSX1 INY - LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING +_CEXSX LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING TAY JMP NEXTOP ;* From a93cc95655a028831a16ceefb4c3609ad869f0f7 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 26 Mar 2017 20:19:36 -0700 Subject: [PATCH 15/58] Check for existing string in pool before copying CS string from aux mem --- README.md | 52 ++-------------------------------------------------- 1 file changed, 2 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 04ce9e4..1464df4 100755 --- a/README.md +++ b/README.md @@ -611,7 +611,7 @@ Numbers can be represented in either decimal (base 10), or hexadecimal (base 16) ## Character and String Literals -A character literal, represented by a single character or an escaped character enclosed in single quotes `'`, can be used wherever a number is used. String literals, a character sequence enclosed in double quotes `"`, can only appear in a data definition. A length byte will be calculated and prepended to the character data. This is the Pascal style of string definition used throughout PLASMA and ProDOS. When referencing the string, its address is used: +A character literal, represented by a single character or an escaped character enclosed in single quotes `'`, can be used wherever a number is used. A length byte will be calculated and prepended to the character data. This is the Pascal style of string definition used throughout PLASMA and ProDOS. When referencing the string, its address is used: ``` char mystring[] = "This is my string; I am very proud of it." @@ -640,55 +640,7 @@ Strings can be used as literals inside expression or as parameters. The above pu puts("This is my string; I am very proud of it.") ``` -just like any proper language. This makes coding a much simpler task when it comes to spitting out strings to the screen. However (there always has to be a 'However'), nothing comes for free. Since PLASMA doesn't have garbage collection, memory is allocated on the stack frame for the string every time it is encountered. Translation: you can easily chew up many K of memory if you aren't careful. The memory is recovered when the function exits, just like the rest of the local variables. - -Don't do this: - -``` -word i - -for i = 0 to 10000 - puts("I am eating all your memory!") -next -``` - -That string will be allocated anew every time through the loop. Instead, you could put the string in initialized memory, create a pointer to it before the loop, or put all the string handling in a function that gets called from inside the loop: - -``` -byte nicestr = "This is a nice string" -word i - -for i = 0 to 10000 - puts(@nicestr) -next -``` - -or: - -``` -word i, nicestr - -nicerstr = "This is a nicer string" -for i = 0 to 10000 - puts(nicestr) -next -``` - -or: - -``` -word i - -def putstr - puts("This is a nice string, too") -end - -for i = 0 to 10000 - putstr -next -``` - -If you are curious as to why in-line strings behave this way, it is due to putting the string constant right into the bytecode stream, which makes it easy to compile and interpret. Also, when bytecode is placed in AUX memory (or extended memory in the Apple ///), it relieves the pressure of keeping all the in-line strings in precious main memory all the time. A normal compiler would move in-line strings into anonymous data memory and reference it from there. PLASMA now has a string pool associated with each function invocation, just like the local variable frame. It grows dynamically as strings are encountered and gives them an address in main memory until the function exits, freeing the string pool for that function. PLASMA is too dumb (and I'm too lazy) to implement a real string manager inside the compiler/VM. That would make for a nice library module, though. +just like any proper language. This makes coding a much simpler task when it comes to spitting out strings to the screen. ## Words From ee8fd77c261fe15402e6b760467e18b9ee9b585a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 26 Mar 2017 20:36:03 -0700 Subject: [PATCH 16/58] Check for existing string in pool before copying CS string from aux mem --- src/samplesrc/rogue.combat.pla | 30 +++++++--------------- src/toolsrc/sb.pla | 2 +- src/vmsrc/plvm02.s | 8 +++--- src/vmsrc/plvm03.s | 46 +++++++++++++++++++++++++++++----- 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/samplesrc/rogue.combat.pla b/src/samplesrc/rogue.combat.pla index fea5868..5af63cf 100644 --- a/src/samplesrc/rogue.combat.pla +++ b/src/samplesrc/rogue.combat.pla @@ -119,7 +119,6 @@ word ascii_entity = @ascii_thief, @ascii_ogre, @ascii_zombie, @ascii_rogue // // Monster types // - byte thief = "Thief", 5 byte ogre = "Ogre", 20 byte zombie = "Zombie", 40 @@ -127,17 +126,6 @@ byte rogue = "Rogue", 80 export word entity = @thief, @ogre, @zombie, @rogue export word entities = 0 -// -// Combat status strings -// - -byte skillstr = "Skill :" -byte healthstr = "Health :" -byte energystr = "Energy :" -byte powerstr = "Power :" -byte lifestr = "Life :" -byte fightstr = "F)ight or R)un?" - // // Combat Return 1 if running away, 0 if end of fight // @@ -157,24 +145,24 @@ export def fight(player, enemy) gotoxy(0, 0) puts(player+name) gotoxy(1, 2) - puts(@skillstr); puti(player->skill) + puts("Skill :"); puti(player->skill) gotoxy(1, 3) - puts(@healthstr); puti(player->health) + puts("Health :"); puti(player->health) gotoxy(1, 4) - puts(@energystr); puti(player->energy) + puts("Energy :"); puti(player->energy) gotoxy(20, 0) puts(entity[enemy->kind]) gotoxy(21, 2) - puts(@powerstr); puti(enemy->power) + puts("Power :"); puti(enemy->power) gotoxy(21, 3) - puts(@lifestr); puti(enemy->life) + puts("Life :"); puti(enemy->life) for e_atck = 0 to 9 gotoxy(0, 10 + e_atck) puts(@ascii_warrior + e_atck * 11) gotoxy(20, 10 + e_atck) puts(ascii_entity[enemy->kind] + e_atck * 11) next - gotoxy(12, 8); puts(@fightstr) + gotoxy(12, 8); puts("F)ight or R)un?") if toupper(getkb()) == 'R' return 1 else @@ -204,10 +192,10 @@ export def fight(player, enemy) entities = enemy=>next_other fin if enemy=>next_other - enemy=>next_other=>prev_other = enemy=>prev_other + enemy=>next_other=>prev_other = enemy=>prev_other fin if enemy=>prev_other - enemy=>prev_other=>next_other = enemy=>next_other + enemy=>prev_other=>next_other = enemy=>next_other fin fin if player->health > e_atck @@ -224,4 +212,4 @@ export def fight(player, enemy) return 0 end -done \ No newline at end of file +done diff --git a/src/toolsrc/sb.pla b/src/toolsrc/sb.pla index 360e10b..34a76e6 100644 --- a/src/toolsrc/sb.pla +++ b/src/toolsrc/sb.pla @@ -90,7 +90,7 @@ word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 // Editor variables // byte nullstr = "" -byte version = "PLASMA ][ SANDBOX VERSION 00.95" +byte version = "PLASMA ][ SANDBOX VERSION 00.96" byte errorstr = "ERROR: $" byte okstr = "OK" byte outofmem = "OUT OF MEMORY!" diff --git a/src/vmsrc/plvm02.s b/src/vmsrc/plvm02.s index 668d4d7..d1b3243 100644 --- a/src/vmsrc/plvm02.s +++ b/src/vmsrc/plvm02.s @@ -786,11 +786,11 @@ CSX DEX TAY ADC IPH STA IPH - LDA PPH ; SCAN POOL FOR STRING ALREADY THERE - STA TMPH - LDA PPL + LDA PPL ; SCAN POOL FOR STRING ALREADY THERE STA TMPL -_CMPPSX LDA TMPH ; CHECK FOR END OF POOL + LDA PPH + STA TMPH +_CMPPSX ;LDA TMPH ; CHECK FOR END OF POOL CMP IFPH BCC _CMPSX ; CHECK FOR MATCHING STRING BNE _CPYSX ; BEYOND END OF POOL, COPY STRING OVER diff --git a/src/vmsrc/plvm03.s b/src/vmsrc/plvm03.s index 8afbd71..5dfa735 100644 --- a/src/vmsrc/plvm03.s +++ b/src/vmsrc/plvm03.s @@ -46,7 +46,7 @@ DSTX = XPAGE+DSTH !WORD $0000 !WORD SEGSTART !WORD SEGEND-SEGSTART - + +SOS $40, SEGREQ ; ALLOCATE SEG 1 AND MAP IT BNE PRHEX LDA #$01 @@ -89,7 +89,7 @@ PRHEX PHA BCC + ADC #6 + STA $880 -FAIL RTS +FAIL RTS SEGREQ !BYTE 4 !WORD $2001 !WORD $9F01 @@ -545,7 +545,41 @@ CS DEX TAY ADC IPH STA IPH - LDA (IP),Y + LDA PPL ; SCAN POOL FOR STRING ALREADY THERE + STA TMPL + LDA PPH + STA TMPH +_CMPPS ;LDA TMPH ; CHECK FOR END OF POOL + CMP IFPH + BCC _CMPS ; CHECK FOR MATCHING STRING + BNE _CPYS ; BEYOND END OF POOL, COPY STRING OVER + LDA TMPL + CMP IFPL + BCS _CPYS ; AT OR BEYOND END OF POOL, COPY STRING OVER +_CMPS LDA (TMP),Y ; COMPARE STRINGS FROM AUX MEM TO STRINGS IN MAIN MEM + CMP (IP),Y ; COMPARE STRING LENGTHS + BNE _CNXTS1 + TAY +_CMPCS LDA (TMP),Y ; COMPARE STRING CHARS FROM END + CMP (IP),Y + BNE _CNXTS + DEY + BNE _CMPCS + LDA TMPL ; MATCH - SAVE EXISTING ADDR ON ESTK AND MOVE ON + STA ESTKL,X + LDA TMPH + STA ESTKH,X + BNE _CEXS +_CNXTS LDY #$00 + LDA (TMP),Y +_CNXTS1 SEC + ADC TMPL + STA TMPL + LDA #$00 + ADC TMPH + STA TMPH + BNE _CMPPS +_CPYS LDA (IP),Y ; COPY STRING FROM AUX TO MAIN MEM POOL TAY ; MAKE ROOM IN POOL AND SAVE ADDR ON ESTK EOR #$FF CLC @@ -556,13 +590,13 @@ CS DEX ADC PPH STA PPH STA ESTKH,X ; COPY STRING FROM AUX MEM BYTECODE TO MAIN MEM POOL -- LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE +_CPYS1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE STA (PP),Y ; ALTWR IS OFF, NO NEED TO CHANGE IT HERE DEY CPY #$FF - BNE - + BNE _CPYS1 INY - LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING +_CEXS LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING TAY JMP NEXTOP ;* From 488f03949436918a3af443823cc4a1c8ae3d8451 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Sat, 8 Apr 2017 18:42:01 -0700 Subject: [PATCH 17/58] Fix constant string ENTER code for A3 VM --- ROGUE.PO | Bin 143360 -> 143360 bytes src/vmsrc/plvm03.s | 1837 +++++++++++++++++++++--------------------- src/vmsrc/soscmd.pla | 978 +++++++++++----------- 3 files changed, 1405 insertions(+), 1410 deletions(-) diff --git a/ROGUE.PO b/ROGUE.PO index a1de91da2c2d98a141a5fedd0f9ff111d6f254fd..96034681dac45840f729e623229a83e7e2927e41 100644 GIT binary patch delta 8838 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 Tm?-luMkr2nYJcu~i#zbYe))fZ delta 1009 zcmYL`Z)jUp7{`kg0k_sItW2Qq8VM0q#Qs)BGlQ`VvYT&Z*4wssK8+?ra9nInnFK#X`FZ{8~kYfy1zn1+M?)_J-@>25eNNa~Z+u9QD@BxUYPk<`u9{gfHUM#=}dKnb~t z*tL@RW4pt}cpfju3wVY5nNGBP{oq`DPAd#9#1~fSfH3e(Ru5}Bp`#vNjh%X85nf^8 zqWQiyy8RjM*arru@P-TOgkv{g$=I%V()*Q8Vc7(G;6w5pjJ>7|rY|ZueM!M;Lb;$` zRdTANe5R(A-={LlkT$C@Q!Pq^l2;lPgyt13KU3geN>99;Ue)rvUpQ#6IoFWB8ulP7xwkOQ$*T#QC7PXHO=Hp`i+8!v_i>MugxX=5EBNzgx(x)fgm(^ z(nAFjLOt$?cwz_m;4BkD=XAcC`wMnB<4Lydp0kAOh1ddZ-E70%5X)c69sMiPjfe;GL&TyxhYEBo;S$!T2 z`A7|%L_)Fx&kENoz_|~q8KwqcUN{fTrz8W63}z-9g3F8-+1o@hh!7Vk?{o(&s14bv f8!qppp7w3c&ADtCx@!gQU0`!;0{$_Q+tBwfj;o$H diff --git a/src/vmsrc/plvm03.s b/src/vmsrc/plvm03.s index 5dfa735..bc82707 100644 --- a/src/vmsrc/plvm03.s +++ b/src/vmsrc/plvm03.s @@ -8,1082 +8,1083 @@ ; ; HARDWARE REGISTERS ; -MEMBANK = $FFEF - !SOURCE "vmsrc/plvmzp.inc" +MEMBANK = $FFEF + !SOURCE "vmsrc/plvmzp.inc" ; ; XPAGE ADDRESSES ; -XPAGE = $1600 -DROPX = XPAGE+DROP -IFPX = XPAGE+IFPH -PPX = XPAGE+PPH -IPX = XPAGE+IPH -TMPX = XPAGE+TMPH -SRCX = XPAGE+SRCH -DSTX = XPAGE+DSTH +XPAGE = $1600 +DROPX = XPAGE+DROP +IFPX = XPAGE+IFPH +PPX = XPAGE+PPH +IPX = XPAGE+IPH +TMPX = XPAGE+TMPH +SRCX = XPAGE+SRCH +DSTX = XPAGE+DSTH ;* ;* SOS ;* - !MACRO SOS .CMD, .LIST { - BRK - !BYTE .CMD - !WORD .LIST - } + !MACRO SOS .CMD, .LIST { + BRK + !BYTE .CMD + !WORD .LIST + } ;* ;* INTERPRETER INSTRUCTION POINTER INCREMENT MACRO ;* - !MACRO INC_IP { - INY - BNE *+4 - INC IPH - } + !MACRO INC_IP { + INY + BNE *+4 + INC IPH + } ;* ;* INTERPRETER HEADER+INITIALIZATION ;* - SEGSTART = $A000 - *= SEGSTART-$0E - !TEXT "SOS NTRP" - !WORD $0000 - !WORD SEGSTART - !WORD SEGEND-SEGSTART + SEGSTART = $A000 + *= SEGSTART-$0E + !TEXT "SOS NTRP" + !WORD $0000 + !WORD SEGSTART + !WORD SEGEND-SEGSTART - +SOS $40, SEGREQ ; ALLOCATE SEG 1 AND MAP IT - BNE PRHEX - LDA #$01 - STA MEMBANK - LDY #$0F ; INSTALL PAGE 0 FETCHOP ROUTINE - LDA #$00 -- LDX PAGE0,Y - STX DROP,Y - STA DROPX,Y - DEY - BPL - - STA TMPX ; CLEAR ALL EXTENDED POINTERS - STA SRCX - STA DSTX - STA PPX ; INIT FRAME & POOL POINTERS - STA IFPX - LDA #SEGSTART - STA PPH - STA IFPH - LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX - JMP SOSCMD -PRHEX PHA - LSR - LSR - LSR - LSR - CLC - ADC #'0' - CMP #':' - BCC + - ADC #6 -+ STA $480 - PLA - AND #$0F - ADC #'0' - CMP #':' - BCC + - ADC #6 -+ STA $880 -FAIL RTS -SEGREQ !BYTE 4 - !WORD $2001 - !WORD $9F01 - !BYTE $10 - !BYTE $00 -PAGE0 = * - !PSEUDOPC $00EF { + +SOS $40, SEGREQ ; ALLOCATE SEG 1 AND MAP IT + BNE FAIL ; PRHEX + LDA #$01 + STA MEMBANK + LDY #$0F ; INSTALL PAGE 0 FETCHOP ROUTINE + LDA #$00 +- LDX PAGE0,Y + STX DROP,Y + STA DROPX,Y + DEY + BPL - + STA TMPX ; CLEAR ALL EXTENDED POINTERS + STA SRCX + STA DSTX + STA PPX ; INIT FRAME & POOL POINTERS + STA IFPX + LDA #SEGSTART + STA PPH + STA IFPH + LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX + JMP SOSCMD +;PRHEX PHA +; LSR +; LSR +; LSR +; LSR +; CLC +; ADC #'0' +; CMP #':' +; BCC + +; ADC #6 +;+ STA $480 +; PLA +; AND #$0F +; ADC #'0' +; CMP #':' +; BCC + +; ADC #6 +;+ STA $481 ;$880 +FAIL STA $0480 + RTS +SEGREQ !BYTE 4 + !WORD $2001 + !WORD $9F01 + !BYTE $10 + !BYTE $00 +PAGE0 = * + !PSEUDOPC $00EF { ;* ;* INTERP BYTECODE INNER LOOP ;* - INX ; DROP - INY ; NEXTOP - BEQ NEXTOPH - LDA $FFFF,Y ; FETCHOP @ $F3, IP MAPS OVER $FFFF @ $F4 - STA OPIDX - JMP (OPTBL) -NEXTOPH INC IPH - BNE FETCHOP + INX ; DROP + INY ; NEXTOP + BEQ NEXTOPH + LDA $FFFF,Y ; FETCHOP @ $F3, IP MAPS OVER $FFFF @ $F4 + STA OPIDX + JMP (OPTBL) +NEXTOPH INC IPH + BNE FETCHOP } ;* ;* SYSTEM INTERPRETER ENTRYPOINT ;* -INTERP PLA - CLC - ADC #$01 +INTERP PLA + CLC + ADC #$01 STA IPL PLA - ADC #$00 + ADC #$00 STA IPH - LDA IFPH - PHA ; SAVE ON STACK FOR LEAVE/RET - LDA IFPL - PHA ; SAVE ON STACK FOR LEAVE/RET - LDA PPL ; SET FP TO PP - STA IFPL - LDA PPH - STA IFPH - LDY #$00 - STY IPX - JMP FETCHOP + LDA IFPH + PHA ; SAVE ON STACK FOR LEAVE/RET + LDA IFPL + PHA ; SAVE ON STACK FOR LEAVE/RET + LDA PPL ; SET FP TO PP + STA IFPL + LDA PPH + STA IFPH + LDY #$00 + STY IPX + JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER ;* -XINTERP PLA +XINTERP PLA STA TMPL PLA STA TMPH - LDY #$03 - LDA (TMP),Y - STA IPX - DEY - LDA (TMP),Y - STA IPH - DEY - LDA (TMP),Y - STA IPL + LDY #$03 + LDA (TMP),Y + STA IPX DEY - LDA IFPH - PHA ; SAVE ON STACK FOR LEAVE/RET - LDA IFPL - PHA ; SAVE ON STACK FOR LEAVE/RET - LDA PPL ; SET FP TO PP - STA IFPL - LDA PPH - STA IFPH - JMP FETCHOP + LDA (TMP),Y + STA IPH + DEY + LDA (TMP),Y + STA IPL + DEY + LDA IFPH + PHA ; SAVE ON STACK FOR LEAVE/RET + LDA IFPL + PHA ; SAVE ON STACK FOR LEAVE/RET + LDA PPL ; SET FP TO PP + STA IFPL + LDA PPH + STA IFPH + JMP FETCHOP ;* ;* INTERNAL DIVIDE ALGORITHM ;* -_NEG LDA #$00 - SEC - SBC ESTKL,X - STA ESTKL,X - LDA #$00 - SBC ESTKH,X - STA ESTKH,X - RTS -_DIV STY IPY - LDY #$11 ; #BITS+1 - LDA #$00 - STA TMPL ; REMNDRL - STA TMPH ; REMNDRH - LDA ESTKH,X - AND #$80 - STA DVSIGN - BPL + - JSR _NEG - INC DVSIGN -+ LDA ESTKH+1,X - BPL + - INX - JSR _NEG - DEX - INC DVSIGN - BNE _DIV1 -+ ORA ESTKL+1,X ; DVDNDL - BEQ _DIVEX -_DIV1 ASL ESTKL+1,X ; DVDNDL - ROL ESTKH+1,X ; DVDNDH - DEY - BCC _DIV1 -_DIVLP ROL TMPL ; REMNDRL - ROL TMPH ; REMNDRH - LDA TMPL ; REMNDRL - CMP ESTKL,X ; DVSRL - LDA TMPH ; REMNDRH - SBC ESTKH,X ; DVSRH - BCC + - STA TMPH ; REMNDRH - LDA TMPL ; REMNDRL - SBC ESTKL,X ; DVSRL - STA TMPL ; REMNDRL - SEC -+ ROL ESTKL+1,X ; DVDNDL - ROL ESTKH+1,X ; DVDNDH - DEY - BNE _DIVLP -_DIVEX INX - LDY IPY - RTS +_NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +_DIV STY IPY + LDY #$11 ; #BITS+1 + LDA #$00 + STA TMPL ; REMNDRL + STA TMPH ; REMNDRH + LDA ESTKH,X + AND #$80 + STA DVSIGN + BPL + + JSR _NEG + INC DVSIGN ++ LDA ESTKH+1,X + BPL + + INX + JSR _NEG + DEX + INC DVSIGN + BNE _DIV1 ++ ORA ESTKL+1,X ; DVDNDL + BEQ _DIVEX +_DIV1 ASL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BCC _DIV1 +_DIVLP ROL TMPL ; REMNDRL + ROL TMPH ; REMNDRH + LDA TMPL ; REMNDRL + CMP ESTKL,X ; DVSRL + LDA TMPH ; REMNDRH + SBC ESTKH,X ; DVSRH + BCC + + STA TMPH ; REMNDRH + LDA TMPL ; REMNDRL + SBC ESTKL,X ; DVSRL + STA TMPL ; REMNDRL + SEC ++ ROL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BNE _DIVLP +_DIVEX INX + LDY IPY + RTS ;* ;* OPCODE TABLE ;* - !ALIGN 255,0 -OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E - !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E - !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E - !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E - !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E - !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E - !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E - !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E + !ALIGN 255,0 +OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E + !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E + !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E + !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E + !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E + !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E + !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E ;* ;* MUL TOS-1 BY TOS ;* -MUL STY IPY - LDY #$10 - LDA ESTKL+1,X - EOR #$FF - STA TMPL - LDA ESTKH+1,X - EOR #$FF - STA TMPH - LDA #$00 - STA ESTKL+1,X ; PRODL -; STA ESTKH+1,X ; PRODH -MULLP LSR TMPH ; MULTPLRH - ROR TMPL ; MULTPLRL - BCS + - STA ESTKH+1,X ; PRODH - LDA ESTKL,X ; MULTPLNDL - ADC ESTKL+1,X ; PRODL - STA ESTKL+1,X - LDA ESTKH,X ; MULTPLNDH - ADC ESTKH+1,X ; PRODH -+ ASL ESTKL,X ; MULTPLNDL - ROL ESTKH,X ; MULTPLNDH - DEY - BNE MULLP - STA ESTKH+1,X ; PRODH - LDY IPY -; INX -; JMP NEXTOP - JMP DROP +MUL STY IPY + LDY #$10 + LDA ESTKL+1,X + EOR #$FF + STA TMPL + LDA ESTKH+1,X + EOR #$FF + STA TMPH + LDA #$00 + STA ESTKL+1,X ; PRODL +; STA ESTKH+1,X ; PRODH +MULLP LSR TMPH ; MULTPLRH + ROR TMPL ; MULTPLRL + BCS + + STA ESTKH+1,X ; PRODH + LDA ESTKL,X ; MULTPLNDL + ADC ESTKL+1,X ; PRODL + STA ESTKL+1,X + LDA ESTKH,X ; MULTPLNDH + ADC ESTKH+1,X ; PRODH ++ ASL ESTKL,X ; MULTPLNDL + ROL ESTKH,X ; MULTPLNDH + DEY + BNE MULLP + STA ESTKH+1,X ; PRODH + LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* NEGATE TOS ;* -NEG LDA #$00 - SEC - SBC ESTKL,X - STA ESTKL,X - LDA #$00 - SBC ESTKH,X - STA ESTKH,X - JMP NEXTOP +NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + JMP NEXTOP ;* ;* DIV TOS-1 BY TOS ;* -DIV JSR _DIV - LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 - BCS NEG - JMP NEXTOP +DIV JSR _DIV + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS NEG + JMP NEXTOP ;* ;* MOD TOS-1 BY TOS ;* -MOD JSR _DIV - LDA TMPL ; REMNDRL - STA ESTKL,X - LDA TMPH ; REMNDRH - STA ESTKH,X - LDA DVSIGN ; REMAINDER IS SIGN OF DIVIDEND - BMI NEG - JMP NEXTOP +MOD JSR _DIV + LDA TMPL ; REMNDRL + STA ESTKL,X + LDA TMPH ; REMNDRH + STA ESTKH,X + LDA DVSIGN ; REMAINDER IS SIGN OF DIVIDEND + BMI NEG + JMP NEXTOP ;* ;* ADD TOS TO TOS-1 ;* -ADD LDA ESTKL,X - CLC - ADC ESTKL+1,X - STA ESTKL+1,X - LDA ESTKH,X - ADC ESTKH+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +ADD LDA ESTKL,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* SUB TOS FROM TOS-1 ;* -SUB LDA ESTKL+1,X - SEC - SBC ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - SBC ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +SUB LDA ESTKL+1,X + SEC + SBC ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + SBC ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ;* ;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 ;* -IDXW LDA ESTKL,X - ASL - ROL ESTKH,X - CLC - ADC ESTKL+1,X - STA ESTKL+1,X - LDA ESTKH,X - ADC ESTKH+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +IDXW LDA ESTKL,X + ASL + ROL ESTKH,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCREMENT TOS ;* -INCR INC ESTKL,X - BNE INCR1 - INC ESTKH,X -INCR1 JMP NEXTOP +INCR INC ESTKL,X + BNE INCR1 + INC ESTKH,X +INCR1 JMP NEXTOP ;* ;* DECREMENT TOS ;* -DECR LDA ESTKL,X - BNE DECR1 - DEC ESTKH,X -DECR1 DEC ESTKL,X - JMP NEXTOP +DECR LDA ESTKL,X + BNE DECR1 + DEC ESTKH,X +DECR1 DEC ESTKL,X + JMP NEXTOP ;* ;* BITWISE COMPLIMENT TOS ;* -COMP LDA #$FF - EOR ESTKL,X - STA ESTKL,X - LDA #$FF - EOR ESTKH,X - STA ESTKH,X - JMP NEXTOP +COMP LDA #$FF + EOR ESTKL,X + STA ESTKL,X + LDA #$FF + EOR ESTKH,X + STA ESTKH,X + JMP NEXTOP ;* ;* BITWISE AND TOS TO TOS-1 ;* -BAND LDA ESTKL+1,X - AND ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - AND ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +BAND LDA ESTKL+1,X + AND ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + AND ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCLUSIVE OR TOS TO TOS-1 ;* -IOR LDA ESTKL+1,X - ORA ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - ORA ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +IOR LDA ESTKL+1,X + ORA ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + ORA ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* EXLUSIVE OR TOS TO TOS-1 ;* -XOR LDA ESTKL+1,X - EOR ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - EOR ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +XOR LDA ESTKL+1,X + EOR ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + EOR ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 LEFT BY TOS ;* -SHL STY IPY - LDA ESTKL,X - CMP #$08 - BCC SHL1 - LDY ESTKL+1,X - STY ESTKH+1,X - LDY #$00 - STY ESTKL+1,X - SBC #$08 -SHL1 TAY - BEQ SHL3 -SHL2 ASL ESTKL+1,X - ROL ESTKH+1,X - DEY - BNE SHL2 -SHL3 LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SHL STY IPY + LDA ESTKL,X + CMP #$08 + BCC SHL1 + LDY ESTKL+1,X + STY ESTKH+1,X + LDY #$00 + STY ESTKL+1,X + SBC #$08 +SHL1 TAY + BEQ SHL3 +SHL2 ASL ESTKL+1,X + ROL ESTKH+1,X + DEY + BNE SHL2 +SHL3 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 RIGHT BY TOS ;* -SHR STY IPY - LDA ESTKL,X - CMP #$08 - BCC SHR2 - LDY ESTKH+1,X - STY ESTKL+1,X - CPY #$80 - LDY #$00 - BCC SHR1 - DEY -SHR1 STY ESTKH+1,X - SEC - SBC #$08 -SHR2 TAY - BEQ SHR4 - LDA ESTKH+1,X -SHR3 CMP #$80 - ROR - ROR ESTKL+1,X - DEY - BNE SHR3 - STA ESTKH+1,X -SHR4 LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SHR STY IPY + LDA ESTKL,X + CMP #$08 + BCC SHR2 + LDY ESTKH+1,X + STY ESTKL+1,X + CPY #$80 + LDY #$00 + BCC SHR1 + DEY +SHR1 STY ESTKH+1,X + SEC + SBC #$08 +SHR2 TAY + BEQ SHR4 + LDA ESTKH+1,X +SHR3 CMP #$80 + ROR + ROR ESTKL+1,X + DEY + BNE SHR3 + STA ESTKH+1,X +SHR4 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* LOGICAL NOT ;* -LNOT LDA ESTKL,X - ORA ESTKH,X - BEQ LNOT1 - LDA #$FF -LNOT1 EOR #$FF - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP +LNOT LDA ESTKL,X + ORA ESTKH,X + BEQ LNOT1 + LDA #$FF +LNOT1 EOR #$FF + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP ;* ;* LOGICAL AND ;* -LAND LDA ESTKL+1,X - ORA ESTKH+1,X - BEQ LAND2 - LDA ESTKL,X - ORA ESTKH,X - BEQ LAND1 - LDA #$FF -LAND1 STA ESTKL+1,X - STA ESTKH+1,X -;LAND2 INX -; JMP NEXTOP -LAND2 JMP DROP +LAND LDA ESTKL+1,X + ORA ESTKH+1,X + BEQ LAND2 + LDA ESTKL,X + ORA ESTKH,X + BEQ LAND1 + LDA #$FF +LAND1 STA ESTKL+1,X + STA ESTKH+1,X +;LAND2 INX +; JMP NEXTOP +LAND2 JMP DROP ;* ;* LOGICAL OR ;* -LOR LDA ESTKL,X - ORA ESTKH,X - ORA ESTKL+1,X - ORA ESTKH+1,X - BEQ LOR1 - LDA #$FF - STA ESTKL+1,X - STA ESTKH+1,X -;LOR1 INX -; JMP NEXTOP -LOR1 JMP DROP +LOR LDA ESTKL,X + ORA ESTKH,X + ORA ESTKL+1,X + ORA ESTKH+1,X + BEQ LOR1 + LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X +;LOR1 INX +; JMP NEXTOP +LOR1 JMP DROP ;* ;* DUPLICATE TOS ;* -DUP DEX - LDA ESTKL+1,X - STA ESTKL,X - LDA ESTKH+1,X - STA ESTKH,X - JMP NEXTOP +DUP DEX + LDA ESTKL+1,X + STA ESTKL,X + LDA ESTKH+1,X + STA ESTKH,X + JMP NEXTOP ;* ;* PUSH FROM EVAL STACK TO CALL STACK ;* -PUSH LDA ESTKL,X - PHA - LDA ESTKH,X - PHA -; INX -; JMP NEXTOP - JMP DROP +PUSH LDA ESTKL,X + PHA + LDA ESTKH,X + PHA +; INX +; JMP NEXTOP + JMP DROP ;* ;* PULL FROM CALL STACK TO EVAL STACK ;* -PULL DEX - PLA - STA ESTKH,X - PLA - STA ESTKL,X - JMP NEXTOP +PULL DEX + PLA + STA ESTKH,X + PLA + STA ESTKL,X + JMP NEXTOP ;* ;* CONSTANT ;* -ZERO DEX - LDA #$00 - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP -CB DEX - +INC_IP - LDA (IP),Y - STA ESTKL,X - LDA #$00 - STA ESTKH,X - JMP NEXTOP +ZERO DEX + LDA #$00 + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +CB DEX + +INC_IP + LDA (IP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP ;* ;* LOAD ADDRESS & LOAD CONSTANT WORD (SAME THING, WITH OR WITHOUT FIXUP) ;* -LA = * -CW DEX - +INC_IP - LDA (IP),Y - STA ESTKL,X - +INC_IP - LDA (IP),Y - STA ESTKH,X - JMP NEXTOP +LA = * +CW DEX + +INC_IP + LDA (IP),Y + STA ESTKL,X + +INC_IP + LDA (IP),Y + STA ESTKH,X + JMP NEXTOP ;* ;* CONSTANT STRING ;* -CS DEX - +INC_IP - TYA ; NORMALIZE IP - CLC - ADC IPL - STA IPL - LDA #$00 - TAY - ADC IPH - STA IPH - LDA PPL ; SCAN POOL FOR STRING ALREADY THERE - STA TMPL - LDA PPH - STA TMPH -_CMPPS ;LDA TMPH ; CHECK FOR END OF POOL - CMP IFPH - BCC _CMPS ; CHECK FOR MATCHING STRING - BNE _CPYS ; BEYOND END OF POOL, COPY STRING OVER - LDA TMPL - CMP IFPL - BCS _CPYS ; AT OR BEYOND END OF POOL, COPY STRING OVER -_CMPS LDA (TMP),Y ; COMPARE STRINGS FROM AUX MEM TO STRINGS IN MAIN MEM - CMP (IP),Y ; COMPARE STRING LENGTHS - BNE _CNXTS1 - TAY -_CMPCS LDA (TMP),Y ; COMPARE STRING CHARS FROM END - CMP (IP),Y - BNE _CNXTS - DEY - BNE _CMPCS - LDA TMPL ; MATCH - SAVE EXISTING ADDR ON ESTK AND MOVE ON - STA ESTKL,X - LDA TMPH - STA ESTKH,X - BNE _CEXS -_CNXTS LDY #$00 - LDA (TMP),Y +CS DEX + +INC_IP + TYA ; NORMALIZE IP + CLC + ADC IPL + STA IPL + LDA #$00 + TAY + ADC IPH + STA IPH + LDA PPL ; SCAN POOL FOR STRING ALREADY THERE + STA TMPL + LDA PPH + STA TMPH +_CMPPS ;LDA TMPH ; CHECK FOR END OF POOL + CMP IFPH + BCC _CMPS ; CHECK FOR MATCHING STRING + BNE _CPYS ; BEYOND END OF POOL, COPY STRING OVER + LDA TMPL + CMP IFPL + BCS _CPYS ; AT OR BEYOND END OF POOL, COPY STRING OVER +_CMPS LDA (TMP),Y ; COMPARE STRINGS FROM AUX MEM TO STRINGS IN MAIN MEM + CMP (IP),Y ; COMPARE STRING LENGTHS + BNE _CNXTS1 + TAY +_CMPCS LDA (TMP),Y ; COMPARE STRING CHARS FROM END + CMP (IP),Y + BNE _CNXTS + DEY + BNE _CMPCS + LDA TMPL ; MATCH - SAVE EXISTING ADDR ON ESTK AND MOVE ON + STA ESTKL,X + LDA TMPH + STA ESTKH,X + BNE _CEXS +_CNXTS LDY #$00 + LDA (TMP),Y _CNXTS1 SEC - ADC TMPL - STA TMPL - LDA #$00 - ADC TMPH - STA TMPH - BNE _CMPPS -_CPYS LDA (IP),Y ; COPY STRING FROM AUX TO MAIN MEM POOL - TAY ; MAKE ROOM IN POOL AND SAVE ADDR ON ESTK - EOR #$FF - CLC - ADC PPL - STA PPL - STA ESTKL,X - LDA #$FF - ADC PPH - STA PPH - STA ESTKH,X ; COPY STRING FROM AUX MEM BYTECODE TO MAIN MEM POOL -_CPYS1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE - STA (PP),Y ; ALTWR IS OFF, NO NEED TO CHANGE IT HERE - DEY - CPY #$FF - BNE _CPYS1 - INY -_CEXS LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING - TAY - JMP NEXTOP + ADC TMPL + STA TMPL + LDA #$00 + ADC TMPH + STA TMPH + BNE _CMPPS +_CPYS LDA (IP),Y ; COPY STRING FROM AUX TO MAIN MEM POOL + TAY ; MAKE ROOM IN POOL AND SAVE ADDR ON ESTK + EOR #$FF + CLC + ADC PPL + STA PPL + STA ESTKL,X + LDA #$FF + ADC PPH + STA PPH + STA ESTKH,X ; COPY STRING FROM AUX MEM BYTECODE TO MAIN MEM POOL +_CPYS1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE + STA (PP),Y ; ALTWR IS OFF, NO NEED TO CHANGE IT HERE + DEY + CPY #$FF + BNE _CPYS1 + INY +_CEXS LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING + TAY + JMP NEXTOP ;* ;* LOAD VALUE FROM ADDRESS TAG ;* -LB LDA ESTKL,X - STA TMPL - LDA ESTKH,X - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - STA ESTKL,X - STY ESTKH,X - LDY IPY - JMP NEXTOP -LW LDA ESTKL,X - STA TMPL - LDA ESTKH,X - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - STA ESTKL,X - INY - LDA (TMP),Y - STA ESTKH,X - LDY IPY - JMP NEXTOP +LB LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + STA ESTKL,X + STY ESTKH,X + LDY IPY + JMP NEXTOP +LW LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP ;* ;* LOAD ADDRESS OF LOCAL FRAME OFFSET ;* -LLA +INC_IP - LDA (IP),Y - DEX - CLC - ADC IFPL - STA ESTKL,X - LDA #$00 - ADC IFPH - STA ESTKH,X - JMP NEXTOP +LLA +INC_IP + LDA (IP),Y + DEX + CLC + ADC IFPL + STA ESTKL,X + LDA #$00 + ADC IFPH + STA ESTKH,X + JMP NEXTOP ;* ;* LOAD VALUE FROM LOCAL FRAME OFFSET ;* -LLB +INC_IP - LDA (IP),Y - STY IPY - TAY - DEX - LDA (IFP),Y - STA ESTKL,X - LDA #$00 - STA ESTKH,X - LDY IPY - JMP NEXTOP -LLW +INC_IP - LDA (IP),Y - STY IPY - TAY - DEX - LDA (IFP),Y - STA ESTKL,X - INY - LDA (IFP),Y - STA ESTKH,X - LDY IPY - JMP NEXTOP +LLB +INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + LDY IPY + JMP NEXTOP +LLW +INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + INY + LDA (IFP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP ;* ;* LOAD VALUE FROM ABSOLUTE ADDRESS ;* -LAB +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - DEX - STA ESTKL,X - STY ESTKH,X - LDY IPY - JMP NEXTOP -LAW +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - DEX - STA ESTKL,X - INY - LDA (TMP),Y - STA ESTKH,X - LDY IPY - JMP NEXTOP +LAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + STY ESTKH,X + LDY IPY + JMP NEXTOP +LAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP ;* ;* STORE VALUE TO ADDRESS ;* -SB LDA ESTKL+1,X - STA TMPL - LDA ESTKH+1,X - STA TMPH - LDA ESTKL,X - STY IPY - LDY #$00 - STA (TMP),Y - LDY IPY - INX -; INX -; JMP NEXTOP - JMP DROP -SW LDA ESTKL+1,X - STA TMPL - LDA ESTKH+1,X - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - INY - LDA ESTKH,X - STA (TMP),Y - LDY IPY - INX -; INX -; JMP NEXTOP - JMP DROP +SB LDA ESTKL+1,X + STA TMPL + LDA ESTKH+1,X + STA TMPH + LDA ESTKL,X + STY IPY + LDY #$00 + STA (TMP),Y + LDY IPY + INX +; INX +; JMP NEXTOP + JMP DROP +SW LDA ESTKL+1,X + STA TMPL + LDA ESTKH+1,X + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + INX +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET ;* -SLB +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP -SLW +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - INY - LDA ESTKH,X - STA (IFP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SLB +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +SLW +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK ;* -DLB +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - LDY IPY - JMP NEXTOP -DLW +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - INY - LDA ESTKH,X - STA (IFP),Y - LDY IPY - JMP NEXTOP +DLB +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY + JMP NEXTOP +DLW +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY + JMP NEXTOP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS ;* -SAB +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - LDA ESTKL,X - STY IPY - LDY #$00 - STA (TMP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP -SAW +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - INY - LDA ESTKH,X - STA (TMP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + LDA ESTKL,X + STY IPY + LDY #$00 + STA (TMP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +SAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK ;* -DAB +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - LDY IPY - JMP NEXTOP -DAW +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - INY - LDA ESTKH,X - STA (TMP),Y - LDY IPY - JMP NEXTOP +DAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + LDY IPY + JMP NEXTOP +DAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + JMP NEXTOP ;* ;* COMPARES ;* -ISEQ LDA ESTKL,X - CMP ESTKL+1,X - BNE ISFLS - LDA ESTKH,X - CMP ESTKH+1,X - BNE ISFLS -ISTRU LDA #$FF - STA ESTKL+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +ISEQ LDA ESTKL,X + CMP ESTKL+1,X + BNE ISFLS + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISFLS +ISTRU LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; -ISNE LDA ESTKL,X - CMP ESTKL+1,X - BNE ISTRU - LDA ESTKH,X - CMP ESTKH+1,X - BNE ISTRU -ISFLS LDA #$00 - STA ESTKL+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +ISNE LDA ESTKL,X + CMP ESTKL+1,X + BNE ISTRU + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISTRU +ISFLS LDA #$00 + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; -ISGE LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - BVC ISGE1 - EOR #$80 -ISGE1 BPL ISTRU - BMI ISFLS +ISGE LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVC ISGE1 + EOR #$80 +ISGE1 BPL ISTRU + BMI ISFLS ; -ISGT LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - BVC ISGT1 - EOR #$80 -ISGT1 BMI ISTRU - BPL ISFLS +ISGT LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVC ISGT1 + EOR #$80 +ISGT1 BMI ISTRU + BPL ISFLS ; -ISLE LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - BVC ISLE1 - EOR #$80 -ISLE1 BPL ISTRU - BMI ISFLS +ISLE LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVC ISLE1 + EOR #$80 +ISLE1 BPL ISTRU + BMI ISFLS ; -ISLT LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - BVC ISLT1 - EOR #$80 -ISLT1 BMI ISTRU - BPL ISFLS +ISLT LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVC ISLT1 + EOR #$80 +ISLT1 BMI ISTRU + BPL ISFLS ;* ;* BRANCHES ;* -BRTRU INX - LDA ESTKH-1,X - ORA ESTKL-1,X - BNE BRNCH -NOBRNCH +INC_IP - +INC_IP - JMP NEXTOP -BRFLS INX - LDA ESTKH-1,X - ORA ESTKL-1,X - BNE NOBRNCH -BRNCH LDA IPH - STA TMPH - LDA IPL - +INC_IP - CLC - ADC (IP),Y - STA TMPL - LDA TMPH - +INC_IP - ADC (IP),Y - STA IPH - LDA TMPL - STA IPL - DEY - DEY - JMP NEXTOP -BREQ INX - LDA ESTKL-1,X - CMP ESTKL,X - BNE NOBRNCH - LDA ESTKH-1,X - CMP ESTKH,X - BEQ BRNCH - BNE NOBRNCH -BRNE INX - LDA ESTKL-1,X - CMP ESTKL,X - BNE BRNCH - LDA ESTKH-1,X - CMP ESTKH,X - BEQ NOBRNCH - BNE BRNCH -BRGT INX - LDA ESTKL-1,X - CMP ESTKL,X - LDA ESTKH-1,X - SBC ESTKH,X - BMI BRNCH - BPL NOBRNCH -BRLT INX - LDA ESTKL,X - CMP ESTKL-1,X - LDA ESTKH,X - SBC ESTKH-1,X - BMI BRNCH - BPL NOBRNCH -IBRNCH LDA IPL - CLC - ADC ESTKL,X - STA IPL - LDA IPH - ADC ESTKH,X - STA IPH -; INX -; JMP NEXTOP - JMP DROP +BRTRU INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE BRNCH +NOBRNCH +INC_IP + +INC_IP + JMP NEXTOP +BRFLS INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE NOBRNCH +BRNCH LDA IPH + STA TMPH + LDA IPL + +INC_IP + CLC + ADC (IP),Y + STA TMPL + LDA TMPH + +INC_IP + ADC (IP),Y + STA IPH + LDA TMPL + STA IPL + DEY + DEY + JMP NEXTOP +BREQ INX + LDA ESTKL-1,X + CMP ESTKL,X + BNE NOBRNCH + LDA ESTKH-1,X + CMP ESTKH,X + BEQ BRNCH + BNE NOBRNCH +BRNE INX + LDA ESTKL-1,X + CMP ESTKL,X + BNE BRNCH + LDA ESTKH-1,X + CMP ESTKH,X + BEQ NOBRNCH + BNE BRNCH +BRGT INX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BMI BRNCH + BPL NOBRNCH +BRLT INX + LDA ESTKL,X + CMP ESTKL-1,X + LDA ESTKH,X + SBC ESTKH-1,X + BMI BRNCH + BPL NOBRNCH +IBRNCH LDA IPL + CLC + ADC ESTKL,X + STA IPL + LDA IPH + ADC ESTKH,X + STA IPH +; INX +; JMP NEXTOP + JMP DROP ;* ;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) ;* -CALL +INC_IP - LDA (IP),Y - STA CALLADR+1 - +INC_IP - LDA (IP),Y - STA CALLADR+2 - LDA IPX - PHA - LDA IPH - PHA - LDA IPL - PHA - TYA - PHA -CALLADR JSR $FFFF - PLA - TAY - PLA - STA IPL - PLA - STA IPH - PLA - STA IPX - JMP NEXTOP +CALL +INC_IP + LDA (IP),Y + STA CALLADR+1 + +INC_IP + LDA (IP),Y + STA CALLADR+2 + LDA IPX + PHA + LDA IPH + PHA + LDA IPL + PHA + TYA + PHA +CALLADR JSR $FFFF + PLA + TAY + PLA + STA IPL + PLA + STA IPH + PLA + STA IPX + JMP NEXTOP ;* ;* INDIRECT CALL TO ADDRESS (NATIVE CODE) ;* -ICAL LDA ESTKL,X - STA ICALADR+1 - LDA ESTKH,X - STA ICALADR+2 - INX - LDA IPX - PHA - LDA IPH - PHA - LDA IPL - PHA - TYA - PHA -ICALADR JSR $FFFF - PLA - TAY - PLA - STA IPL - PLA - STA IPH - PLA - STA IPX - JMP NEXTOP +ICAL LDA ESTKL,X + STA ICALADR+1 + LDA ESTKH,X + STA ICALADR+2 + INX + LDA IPX + PHA + LDA IPH + PHA + LDA IPL + PHA + TYA + PHA +ICALADR JSR $FFFF + PLA + TAY + PLA + STA IPL + PLA + STA IPH + PLA + STA IPX + JMP NEXTOP ;* ;* ENTER FUNCTION WITH FRAME SIZE AND PARAM COUNT ;* -;* -;* ENTER FUNCTION WITH FRAME SIZE AND PARAM COUNT -;* -ENTER INY - LDA (IP),Y - PHA ; SAVE ON STACK FOR LEAVE - EOR #$FF - SEC - ADC IFPL - STA IFPL - BCS + - DEC IFPH -+ INY - LDA (IP),Y - ASL - TAY - BEQ + -- LDA ESTKH,X - DEY - STA (IFP),Y - LDA ESTKL,X - INX - DEY - STA (IFP),Y - BNE - -+ LDY #$02 - JMP NEXTOP +ENTER INY + LDA (IP),Y + PHA ; SAVE ON STACK FOR LEAVE + EOR #$FF + SEC + ADC PPL + STA PPL + STA IFPL + LDA #$FF + ADC PPH + STA PPH + STA IFPH + INY + LDA (IP),Y + ASL + TAY + BEQ + +- LDA ESTKH,X + DEY + STA (IFP),Y + LDA ESTKL,X + INX + DEY + STA (IFP),Y + BNE - ++ LDY #$02 + JMP NEXTOP ;* ;* LEAVE FUNCTION ;* -LEAVE PLA - CLC - ADC IFPL - STA PPL - LDA #$00 - ADC IFPH - STA PPH - PLA ; RESTORE PREVIOUS FRAME - STA IFPL - PLA - STA IFPH - RTS +LEAVE PLA + CLC + ADC IFPL + STA PPL + LDA #$00 + ADC IFPH + STA PPH + PLA ; RESTORE PREVIOUS FRAME + STA IFPL + PLA + STA IFPH + RTS ; -RET LDA IFPL ; DEALLOCATE POOL - STA PPL - LDA IFPH - STA PPH - PLA ; RESTORE PREVIOUS FRAME - STA IFPL - PLA - STA IFPH - RTS -SOSCMD = * - !SOURCE "vmsrc/soscmd.a" -SEGEND = * +RET LDA IFPL ; DEALLOCATE POOL + STA PPL + LDA IFPH + STA PPH + PLA ; RESTORE PREVIOUS FRAME + STA IFPL + PLA + STA IFPH + RTS +SOSCMD = * + !SOURCE "vmsrc/soscmd.a" +SEGEND = * diff --git a/src/vmsrc/soscmd.pla b/src/vmsrc/soscmd.pla index 1fac784..6abe962 100644 --- a/src/vmsrc/soscmd.pla +++ b/src/vmsrc/soscmd.pla @@ -48,12 +48,6 @@ byte perr, terr, lerr // byte console[] = ".CONSOLE" byte autorun[] = "AUTORUN" -byte verstr[] = "PLASMA " -byte freestr[] = "MEM FREE:$" -byte errorstr[] = "ERR:$" -byte okstr[] = "OK" -byte huhstr[] = "?\n" -byte devtovol[] = " => /" byte textmode[] = 16, 0, 15 byte hexchar[] = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' // @@ -91,19 +85,19 @@ byte execstr[] = "MODEXEC" byte modadrstr[] = "MODADDR" byte argstr[] = "ARGS" byte prefix[] // Overlay with exported symbols table -word exports[] = @sysstr, @syscall -word = @callstr, @call -word = @putcstr, @cout -word = @putlnstr, @crout -word = @putsstr, @prstr -word = @getcstr, @cin -word = @getsstr, @rdstr -word = @hpmarkstr, @markheap -word = @hpallocstr,@allocheap -word = @hpalignstr,@allocalignheap -word = @hprelstr, @releaseheap -word = @memsetstr, @memset -word = @memcpystr, @memcpy +word exports[] = @sysstr, @syscall +word = @callstr, @call +word = @putcstr, @cout +word = @putlnstr, @crout +word = @putsstr, @prstr +word = @getcstr, @cin +word = @getsstr, @rdstr +word = @hpmarkstr, @markheap +word = @hpallocstr,@allocheap +word = @hpalignstr,@allocalignheap +word = @hprelstr, @releaseheap +word = @memsetstr, @memset +word = @memcpystr, @memcpy word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt @@ -120,27 +114,27 @@ word syslibsym = @exports // SYSCALL(CMD, PARAMS) // asm syscall - LDA ESTKL,X - LDY ESTKH,X - STA PARAMS - STY PARAMS+1 - INX - LDA ESTKL,X - STA CMD - BRK -CMD !BYTE 00 -PARAMS !WORD 0000 - LDY #$00 - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + LDY ESTKH,X + STA PARAMS + STY PARAMS+1 + INX + LDA ESTKL,X + STA CMD + BRK +CMD !BYTE 00 +PARAMS !WORD 0000 + LDY #$00 + STA ESTKL,X + STY ESTKH,X + RTS end // // CALL 6502 ROUTINE // CALL(AREG, XREG, YREG, STATUS, ADDR) // asm call -REGVALS = SRC +REGVALS = SRC PHP LDA ESTKL,X STA TMPL @@ -175,7 +169,7 @@ REGVALS = SRC STY ESTKH,X PLP RTS -JMPTMP JMP (TMP) +JMPTMP JMP (TMP) end // // SET MEMORY TO VALUE @@ -183,111 +177,111 @@ end // With optimizations from Peter Ferrie // asm memset - LDA ESTKL+2,X - STA DSTL - LDA ESTKH+2,X - STA DSTH - LDY ESTKL,X - BEQ + - INC ESTKH,X - LDY #$00 -+ LDA ESTKH,X - BEQ SETMEX -SETMLPL CLC - LDA ESTKL+1,X -SETMLPH STA (DST),Y - DEC ESTKL,X - BEQ ++ -- INY - BEQ + --- BCS SETMLPL - SEC - LDA ESTKH+1,X - BCS SETMLPH -+ INC DSTH - BNE -- -++ DEC ESTKH,X - BNE - -SETMEX INX - INX - RTS + LDA ESTKL+2,X + STA DSTL + LDA ESTKH+2,X + STA DSTH + LDY ESTKL,X + BEQ + + INC ESTKH,X + LDY #$00 ++ LDA ESTKH,X + BEQ SETMEX +SETMLPL CLC + LDA ESTKL+1,X +SETMLPH STA (DST),Y + DEC ESTKL,X + BEQ ++ +- INY + BEQ + +-- BCS SETMLPL + SEC + LDA ESTKH+1,X + BCS SETMLPH ++ INC DSTH + BNE -- +++ DEC ESTKH,X + BNE - +SETMEX INX + INX + RTS end // // COPY MEMORY // MEMCPY(DSTADDR, SRCADDR, SIZE) // asm memcpy - INX - INX - LDA ESTKL-2,X - ORA ESTKH-2,X - BEQ CPYMEX - LDA ESTKL-1,X - CMP ESTKL,X - LDA ESTKH-1,X - SBC ESTKH,X - BCC REVCPY + INX + INX + LDA ESTKL-2,X + ORA ESTKH-2,X + BEQ CPYMEX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BCC REVCPY ; ; FORWARD COPY ; - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL-1,X - STA SRCL - LDA ESTKH-1,X - STA SRCH - LDY ESTKL-2,X - BEQ FORCPYLP - INC ESTKH-2,X - LDY #$00 -FORCPYLP LDA (SRC),Y - STA (DST),Y - INY - BNE + - INC DSTH - INC SRCH -+ DEC ESTKL-2,X - BNE FORCPYLP - DEC ESTKH-2,X - BNE FORCPYLP - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL-1,X + STA SRCL + LDA ESTKH-1,X + STA SRCH + LDY ESTKL-2,X + BEQ FORCPYLP + INC ESTKH-2,X + LDY #$00 +FORCPYLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL-2,X + BNE FORCPYLP + DEC ESTKH-2,X + BNE FORCPYLP + RTS ; ; REVERSE COPY ; -REVCPY ;CLC - LDA ESTKL-2,X - ADC ESTKL,X - STA DSTL - LDA ESTKH-2,X - ADC ESTKH,X - STA DSTH - CLC - LDA ESTKL-2,X - ADC ESTKL-1,X - STA SRCL - LDA ESTKH-2,X - ADC ESTKH-1,X - STA SRCH - DEC DSTH - DEC SRCH - LDY #$FF - LDA ESTKL-2,X - BEQ REVCPYLP - INC ESTKH-2,X -REVCPYLP LDA (SRC),Y - STA (DST),Y - DEY - CPY #$FF - BNE + - DEC DSTH - DEC SRCH -+ DEC ESTKL-2,X - BNE REVCPYLP - DEC ESTKH-2,X - BNE REVCPYLP -CPYMEX RTS +REVCPY ;CLC + LDA ESTKL-2,X + ADC ESTKL,X + STA DSTL + LDA ESTKH-2,X + ADC ESTKH,X + STA DSTH + CLC + LDA ESTKL-2,X + ADC ESTKL-1,X + STA SRCL + LDA ESTKH-2,X + ADC ESTKH-1,X + STA SRCH + DEC DSTH + DEC SRCH + LDY #$FF + LDA ESTKL-2,X + BEQ REVCPYLP + INC ESTKH-2,X +REVCPYLP LDA (SRC),Y + STA (DST),Y + DEY + CPY #$FF + BNE + + DEC DSTH + DEC SRCH ++ DEC ESTKL-2,X + BNE REVCPYLP + DEC ESTKH-2,X + BNE REVCPYLP +CPYMEX RTS end // // COPY FROM MAIN MEM TO EXT MEM. @@ -295,39 +289,39 @@ end // MEMXCPY(DSTSEG, SRC, SIZE) // asm memxcpy - LDA ESTKL,X - ORA ESTKH,X - BEQ CPYXMEX - LDY #$00 - STY DSTL - LDA ESTKH+2,X - CLC - ADC #$60 - STA DSTH - LDA ESTKL+2,X - ORA #$80 - STA DSTX - DEC DSTX - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - INC ESTKH,X -CPYXLP LDA (SRC),Y - STA (DST),Y - INY - BNE + - INC DSTH - INC SRCH -+ DEC ESTKL,X - BNE CPYXLP - DEC ESTKH,X - BNE CPYXLP - LDA #$00 - STA DSTX -CPYXMEX INX - INX - RTS + LDA ESTKL,X + ORA ESTKH,X + BEQ CPYXMEX + LDY #$00 + STY DSTL + LDA ESTKH+2,X + CLC + ADC #$60 + STA DSTH + LDA ESTKL+2,X + ORA #$80 + STA DSTX + DEC DSTX + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + INC ESTKH,X +CPYXLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL,X + BNE CPYXLP + DEC ESTKH,X + BNE CPYXLP + LDA #$00 + STA DSTX +CPYXMEX INX + INX + RTS end // // POKE BYTE VAL INTO EXT MEM. @@ -335,87 +329,87 @@ end // XPOKEB(SEG, DST, BYTEVAL) // asm xpokeb - LDA ESTKL+1,X - STA DSTL - LDA ESTKH+1,X - CLC - ADC #$60 - STA DSTH - LDA ESTKL+2,X - ORA #$80 - STA DSTX - DEC DSTX - LDY #$00 - LDA ESTKL,X - STA (DST),Y - STY DSTX - INX - INX - RTS + LDA ESTKL+1,X + STA DSTL + LDA ESTKH+1,X + CLC + ADC #$60 + STA DSTH + LDA ESTKL+2,X + ORA #$80 + STA DSTX + DEC DSTX + LDY #$00 + LDA ESTKL,X + STA (DST),Y + STY DSTX + INX + INX + RTS end // // Unsigned word comparisons. // asm uword_isge - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isle - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isgt - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_islt - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end // // Addresses of internal routines. // asm interp - DEX - LDA #XINTERP - STA ESTKH,X - RTS + DEX + LDA #XINTERP + STA ESTKH,X + RTS end // // A DCI string is one that has the high bit set for every character except the last. @@ -433,28 +427,28 @@ end // return len //end asm dcitos - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDY #$00 -- LDA (SRC),Y - CMP #$80 - AND #$7F - INY - STA (DST),Y - BCS - - TYA - LDY #$00 - STA (DST),Y - INX - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDY #$00 +- LDA (SRC),Y + CMP #$80 + AND #$7F + INY + STA (DST),Y + BCS - + TYA + LDY #$00 + STA (DST),Y + INX + STA ESTKL,X + STY ESTKH,X + RTS end //def stodci(str, dci) // byte len, c @@ -466,50 +460,50 @@ end // len = len - 1 // (dci).[len] = c // while len -// c = toupper((str).[len]) | $80 -// len = len - 1 -// (dci).[len] = c +// c = toupper((str).[len]) | $80 +// len = len - 1 +// (dci).[len] = c // loop // return ^str //end asm stodci - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - INX - LDY #$00 - LDA (SRC),Y - BEQ ++ - TAY - LDA (SRC),Y - JSR TOUPR - BNE + -- LDA (SRC),Y - JSR TOUPR - ORA #$80 -+ DEY - STA (DST),Y - BNE - - LDA (SRC),Y -++ STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + INX + LDY #$00 + LDA (SRC),Y + BEQ ++ + TAY + LDA (SRC),Y + JSR TOUPR + BNE + +- LDA (SRC),Y + JSR TOUPR + ORA #$80 ++ DEY + STA (DST),Y + BNE - + LDA (SRC),Y +++ STA ESTKL,X + STY ESTKH,X + RTS end asm toupper - LDA ESTKL,X -TOUPR AND #$7F - CMP #'a' - BCC + - CMP #'z'+1 - BCS + - SBC #$1F -+ STA ESTKL,X - RTS + LDA ESTKL,X +TOUPR AND #$7F + CMP #'a' + BCC + + CMP #'z'+1 + BCS + + SBC #$1F ++ STA ESTKL,X + RTS end // // Module symbols are entered into the symbol table @@ -528,25 +522,25 @@ end // return dci //end asm modtosym - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDA ESTKL,X - STA ESTKL+1,X - STA DSTL - LDA ESTKH,X - STA ESTKH+1,X - STA DSTH - INX - LDY #$00 - LDA #'#'+$80 -- STA (DST),Y - ASL - LDA (SRC),Y - INY - BCS - - RTS + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDA ESTKL,X + STA ESTKL+1,X + STA DSTL + LDA ESTKH,X + STA ESTKH+1,X + STA DSTH + INX + LDY #$00 + LDA #'#'+$80 +- STA (DST),Y + ASL + LDA (SRC),Y + INY + BCS - + RTS end // // Lookup routines. @@ -569,53 +563,53 @@ end // loop // return 0 asm lookuptbl - LDY #$00 - STY DSTL - LDA ESTKH,X - CLC - ADC #$60 - STA DSTH - LDA ESTKL,X - ORA #$80 - STA DSTX - DEC DSTX - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH -- LDA (DST),Y - BEQ + - CMP (SRC),Y - BNE ++ - INY - ASL - BCS - - LDA (DST),Y - PHA - INY - LDA (DST),Y - TAY - PLA -+ INX - STA ESTKL,X - STY ESTKH,X - LDA #$00 - STA DSTX - RTS -++ LDY #$00 --- LDA (DST),Y - INC DSTL - BEQ + ---- ASL - BCS -- - LDA #$02 - ADC DSTL - STA DSTL - BCC - - INC DSTH - BCS - -+ INC DSTH - BNE --- + LDY #$00 + STY DSTL + LDA ESTKH,X + CLC + ADC #$60 + STA DSTH + LDA ESTKL,X + ORA #$80 + STA DSTX + DEC DSTX + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH +- LDA (DST),Y + BEQ + + CMP (SRC),Y + BNE ++ + INY + ASL + BCS - + LDA (DST),Y + PHA + INY + LDA (DST),Y + TAY + PLA ++ INX + STA ESTKL,X + STY ESTKH,X + LDA #$00 + STA DSTX + RTS +++ LDY #$00 +-- LDA (DST),Y + INC DSTL + BEQ + +--- ASL + BCS -- + LDA #$02 + ADC DSTL + STA DSTL + BCC - + INC DSTH + BCS - ++ INC DSTH + BNE --- end // // SOS routines @@ -790,7 +784,7 @@ end def cout(ch) if ch == $0D ch = $0A0D - write(refcons, @ch, 2) + write(refcons, @ch, 2) else write(refcons, @ch, 1) fin @@ -904,12 +898,12 @@ def lookupextern(esd, index) esd = esd + dcitos(esd, @str) if esd->0 & $10 and esd->1 == index addr = lookupsym(sym) - if !addr + if !addr lerr = $81 - cout('?') - prstr(@str) - crout - fin + cout('?') + prstr(@str) + crout + fin return addr fin esd = esd + 3 @@ -950,73 +944,73 @@ def loadmod(mod) refnum = open(@filename, O_READ) if refnum > 0 rdlen = read(refnum, @header, 128) - modsize = header:0 - moddep = @header.1 - defofst = modsize + modsize = header:0 + moddep = @header.1 + defofst = modsize init = 0 if rdlen > 4 and header:2 == $DA7E // DAVE = magic number :-) // // This is an EXTended RELocatable (data+bytecode) module. // - systemflags = header:4 | systemflags + systemflags = header:4 | systemflags defofst = header:6 defcnt = header:8 init = header:10 moddep = @header.12 - // - // Load module dependencies. - // + // + // Load module dependencies. + // while ^moddep if !lookupmod(moddep) - if refnum - close(refnum) - refnum = 0 - fin + if refnum + close(refnum) + refnum = 0 + fin if loadmod(moddep) < 0 - return -perr - fin + return -perr + fin fin moddep = moddep + dcitos(moddep, @str) loop - // - // Init def table. - // - deftbl = allocheap(defcnt * 6 + 1) - deflast = deftbl - ^deflast = 0 - if !refnum - // - // Reset read pointer. - // - refnum = open(@filename, O_READ) - rdlen = read(refnum, @header, 128) - fin + // + // Init def table. + // + deftbl = allocheap(defcnt * 6 + 1) + deflast = deftbl + ^deflast = 0 + if !refnum + // + // Reset read pointer. + // + refnum = open(@filename, O_READ) + rdlen = read(refnum, @header, 128) + fin fin - // - // Alloc heap space for relocated module (data + bytecode). - // - moddep = moddep + 1 - modfix = moddep - @header.2 // Adjust to skip header - modsize = modsize - modfix - rdlen = rdlen - modfix - 2 - modaddr = allocheap(modsize) - memcpy(modaddr, moddep, rdlen) - // - // Read in remainder of module into memory for fixups. - // - addr = modaddr + // + // Alloc heap space for relocated module (data + bytecode). + // + moddep = moddep + 1 + modfix = moddep - @header.2 // Adjust to skip header + modsize = modsize - modfix + rdlen = rdlen - modfix - 2 + modaddr = allocheap(modsize) + memcpy(modaddr, moddep, rdlen) + // + // Read in remainder of module into memory for fixups. + // + addr = modaddr repeat addr = addr + rdlen rdlen = read(refnum, addr, 4096) until rdlen <= 0 close(refnum) - // - // Add module to symbol table. - // - addmod(mod, modaddr) - // - // Apply all fixups and symbol import/export. - // + // + // Add module to symbol table. + // + addmod(mod, modaddr) + // + // Apply all fixups and symbol import/export. + // modfix = modaddr - modfix bytecode = defofst + modfix - MODADDR modend = modaddr + modsize @@ -1024,38 +1018,38 @@ def loadmod(mod) esd = rld // Extern+Entry Symbol Directory while ^esd // Scan to end of ESD esd = esd + 4 - loop + loop esd = esd + 1 - // - // Locate bytecode defs in allocated segment. - // - modseg[modid] = seg_find($00, @codeseg, @defaddr, (rld - bytecode + 255) >> 8, modid + $12) - if perr - return -perr - fin - modid = modid + 1 - defext = (codeseg.0 | $80) - 1 - defaddr = (codeseg & $FF00) + $6000 + // + // Locate bytecode defs in allocated segment. + // + modseg[modid] = seg_find($00, @codeseg, @defaddr, (rld - bytecode + 255) >> 8, modid + $12) + if perr + return -perr + fin + modid = modid + 1 + defext = (codeseg.0 | $80) - 1 + defaddr = (codeseg & $FF00) + $6000 // // Run through the Re-Location Dictionary. // while ^rld if ^rld == $02 - // - // This is a bytcode def entry - add it to the def directory. - // + // + // This is a bytcode def entry - add it to the def directory. + // adddef(defext, rld=>1 - defofst + defaddr, @deflast) else addr = rld=>1 + modfix if uword_isge(addr, modaddr) // Skip fixups to header if ^rld & $80 // WORD sized fixup. fixup = *addr - else // BYTE sized fixup. + else // BYTE sized fixup. fixup = ^addr fin if ^rld & $10 // EXTERN reference. fixup = fixup + lookupextern(esd, rld->3) - else // INTERN fixup. + else // INTERN fixup. fixup = fixup + modfix - MODADDR if uword_isge(fixup, bytecode) // @@ -1066,44 +1060,44 @@ def loadmod(mod) fin if ^rld & $80 // WORD sized fixup. *addr = fixup - else // BYTE sized fixup. + else // BYTE sized fixup. ^addr = fixup fin fin fin rld = rld + 4 loop - // + // // Run through the External/Entry Symbol Directory. - // + // while ^esd sym = esd esd = esd + dcitos(esd, @str) if ^esd & $08 - // + // // EXPORT symbol - add it to the global symbol table. - // + // addr = esd=>1 + modfix - MODADDR if uword_isge(addr, bytecode) - // - // Use the def directory address for bytecode. - // + // + // Use the def directory address for bytecode. + // addr = lookupdef(addr - bytecode + defaddr, deftbl) fin addsym(sym, addr) fin esd = esd + 3 loop - if defext - // - // Copy bytecode to code segment. - // - memxcpy(codeseg, bytecode, modsize - (bytecode - modaddr)) - fin - // - // Free up end-of-module main memory. - // - releaseheap(bytecode) + if defext + // + // Copy bytecode to code segment. + // + memxcpy(codeseg, bytecode, modsize - (bytecode - modaddr)) + fin + // + // Free up end-of-module main memory. + // + releaseheap(bytecode) else return -perr fin @@ -1134,14 +1128,14 @@ def volumes for i = $01 to $18 if dev_info(i, @devname, @info, 11) == 0 - prstr(@devname) - if volume(@devname, @volname, @ttlblks, @freblks) == 0 - prstr(@devtovol) - prstr(@volname) - cout('/') - fin - crout - fin + prstr(@devname) + if volume(@devname, @volname, @ttlblks, @freblks) == 0 + prstr(" => ") + prstr(@volname) + cout('/') + fin + crout + fin next perr = 0 end @@ -1183,12 +1177,12 @@ def catalog(optpath) if type & $F0 == $D0 // Is it a directory? cout('/') len = len + 1 - elsif entry->$10 == $FF - cout('-') - len = len + 1 - elsif entry->$10 == $FE - cout('+') - len = len + 1 + elsif entry->$10 == $FF + cout('-') + len = len + 1 + elsif entry->$10 == $FE + cout('+') + len = len + 1 fin for len = 19 - len downto 0 cout(' ') @@ -1227,9 +1221,9 @@ def striptrail(strptr) for i = 1 to ^strptr if (strptr)[i] <= ' ' - ^strptr = i - 1 - return - fin + ^strptr = i - 1 + return + fin next end def parsecmd(strptr) @@ -1252,20 +1246,20 @@ def execmod(modfile) perr = 1 if stodci(modfile, @moddci) saveheap = heap - savesym = lastsym - saveflags = systemflags - if loadmod(@moddci) < modkeep - lastsym = savesym - heap = saveheap - while modid - modid = modid - 1 - seg_release(modseg[modid]) - loop + savesym = lastsym + saveflags = systemflags + if loadmod(@moddci) < modkeep + lastsym = savesym + heap = saveheap + while modid + modid = modid - 1 + seg_release(modseg[modid]) + loop else - modid = 0 - fin - xpokeb(symtbl.0, lastsym, 0) - systemflags = saveflags + modid = 0 + fin + xpokeb(symtbl.0, lastsym, 0) + systemflags = saveflags fin return -perr end @@ -1299,12 +1293,12 @@ else // // Print some startup info. // - prstr(@verstr) + prstr("PLASMA ") prbyte(version.1) cout('.') prbyte(version.0) crout - prstr(@freestr) + prstr("MEM:$") prword(availheap) crout fin @@ -1316,32 +1310,32 @@ while 1 if ^cmdptr when toupper(parsecmd(cmdptr)) is 'Q' - quit - is 'C' - catalog(cmdptr) - break - is 'P' - setpfx(cmdptr) - break - is 'V' - volumes - break - is '+' - execmod(cmdptr) - write(refcons, @textmode, 3) - break - otherwise - prstr(@huhstr) + quit + is 'C' + catalog(cmdptr) + break + is 'P' + setpfx(cmdptr) + break + is 'V' + volumes + break + is '+' + execmod(cmdptr) + write(refcons, @textmode, 3) + break + otherwise + prstr("?\n") wend if perr - terr = perr - prstr(@errorstr) - prbyte(terr) - perr = 0 + terr = perr + prstr("ERR:$") + prbyte(terr) + perr = 0 else - prstr(@okstr) + prstr("OK\n") fin - crout() + crout() fin prstr(getpfx(@prefix)) cmdptr = rdstr($BA) From 2118af149b3e9595638cf7b2da4d6320fa4cc638 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Tue, 25 Apr 2017 11:54:45 -0700 Subject: [PATCH 18/58] Add embedded PLASMA sample --- src/samplesrc/a2pwm/a2pwm.s | 395 ++++++++++++ src/samplesrc/a2pwm/hilopwm.pla | 267 ++++++++ src/samplesrc/a2pwm/lfo.po | Bin 0 -> 143360 bytes src/samplesrc/a2pwm/lfotbl.s | 32 + src/samplesrc/a2pwm/makefile | 28 + src/samplesrc/a2pwm/pwmvm.s | 1007 +++++++++++++++++++++++++++++++ src/samplesrc/a2pwm/util.pla | 404 +++++++++++++ 7 files changed, 2133 insertions(+) create mode 100755 src/samplesrc/a2pwm/a2pwm.s create mode 100755 src/samplesrc/a2pwm/hilopwm.pla create mode 100755 src/samplesrc/a2pwm/lfo.po create mode 100755 src/samplesrc/a2pwm/lfotbl.s create mode 100755 src/samplesrc/a2pwm/makefile create mode 100755 src/samplesrc/a2pwm/pwmvm.s create mode 100644 src/samplesrc/a2pwm/util.pla diff --git a/src/samplesrc/a2pwm/a2pwm.s b/src/samplesrc/a2pwm/a2pwm.s new file mode 100755 index 0000000..11f766b --- /dev/null +++ b/src/samplesrc/a2pwm/a2pwm.s @@ -0,0 +1,395 @@ +;**************************************************************** +;* +;* PWM SOUND ROUTINES +;* +;**************************************************************** +;* +;* PWM ZERO PAGE LOCATIONS +;* +SPEAKER = $C030 +HFO = $08 +LFO = $09 +LFOINDEX= $0A ; IF LFOUSRH == 0 +LFOUSRL = $0A +LFOUSRH = $0B +ATK = $0C +DCY = $0D +SUS = $0E +RLS = $0F +ATKINCL = $10 +ATKINCH = $11 +DCYINCL = $12 +DCYINCH = $13 +RLSINCL = $14 +RLSINCH = $15 +ADSRL = $16 +ADSRH = $17 +ADSRINCL= $18 +ADSRINCH= $19 +TONELEN = $1B +LPCNT = $1C +HFOCNT = $1D +LFOPOSL = $1E +LFOPOSH = $1F +LFOPTR = $00 +LFOPTRL = LFOPTR +LFOPTRH = LFOPTRL+1 +;* +;* PWM ENTRY POINT +;* +HILOPWM LDA LFOUSRL + LDX LFOUSRH + BNE + ; USER SUPPLIED WAVEFORM + LDX #>LFOTBL + ASL + ASL + ASL + ASL + ASL ++ STA LFOPTRL + STX LFOPTRH + PHP + SEI + LDY #$00 + STY LFOPOSL +; STY LFOPOSH + STY LPCNT + STY ADSRL +; STY ADSRH + LDA #$02 + STA HFOCNT +ATTACK LDX #$0F + LDA ATK + BEQ DECAY + LDX #$00 + STA TONELEN + LDA ATKINCL + STA ADSRINCL + LDA ATKINCH + STA ADSRINCH + JSR HILOSND +DECAY LDA DCY + BEQ SUSTAIN + STA TONELEN + LDA #$00 ; REVERSE ATTACK RATE + SEC + SBC DCYINCL + STA ADSRINCL + LDA #$00 + SBC DCYINCH + STA ADSRINCH + JSR HILOSND +SUSTAIN LDA SUS + BEQ RELEASE + STA TONELEN + LDA #$00 ; SUSTAIN DOESN'T ALTER VOLUME + STA ADSRINCL + STA ADSRINCH + JSR HILOSND +RELEASE LDA RLS + BEQ PWMEXIT + STA TONELEN + LDA #$00 ; REVERSE RELEASE RATE + SEC + SBC RLSINCL + STA ADSRINCL + LDA #$00 + SBC RLSINCH + STA ADSRINCH + JSR HILOSND +PWMEXIT PLP + RTS +PWMSND CLC ; 1, 2 + LDA ADSRL ; 2, 3 + ADC ADSRINCL ; 2, 3 + STA TMP ; 2, 3 + TXA ; 1, 2 + ADC ADSRINCH ; 2, 3 + DEC LPCNT ; 2, 5 + ;------ + ;12,21 + + BNE HILOSND ; 2, 2 + AND #$0F ; 2, 2 + TAX ; 1, 2 + LDA TMP ; 2, 3 + STA ADSRL ; 2, 3 + DEC TONELEN ; 2, 5 + BEQ PWMRET ; 2, 2 + DEC HFOCNT ; 2, 5 + BEQ SPKRON ; 2, 2 + CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + NOP ; 1, 2 + JMP PWMSND ; 3, 3 + ;------ + ;55,79 + +; BNE HILOSND ; , 3 +HILOSND DEC HFOCNT ; 2, 5 + BNE + ; 2, 2 +SPKRON BIT SPEAKER ; 3, 4 +SPKRPWM JMP PWM1 ; 3, 3+62 + ;------ + ;10,79 + +; BNE HILOSND ; , 3 +; DEC HFOCNT ; , 5 +; BNE + ; , 3 ++ BNE ++ ; 2, 3 +++ NOP ; 1, 2 + NOP ; 1, 2 + NOP ; 1, 2 + NOP ; 1, 2 + NOP ; 1, 2 + NOP ; 1, 2 + NOP ; 1, 2 + CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + JMP PWMSND ; 3, 3 + ;------ + ;44,79 +PWMRET RTS +;* +;* 4 BIT x 4 BIT TO 3.5 BIT MULTIPLY TABLE +;* + !ALIGN 255,0 +MUL4X4 !BYTE $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 + !BYTE $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 + !BYTE $00, $00, $00, $00, $00, $00, $00, $00, $20, $20, $20, $20, $20, $20, $20, $20 + !BYTE $00, $00, $00, $00, $00, $00, $20, $20, $20, $20, $20, $20, $20, $20, $20, $20 + !BYTE $00, $00, $00, $00, $20, $20, $20, $20, $20, $20, $20, $20, $40, $40, $40, $40 + !BYTE $00, $00, $00, $00, $20, $20, $20, $20, $20, $20, $40, $40, $40, $40, $40, $40 + !BYTE $00, $00, $00, $20, $20, $20, $20, $20, $40, $40, $40, $40, $40, $40, $60, $60 + !BYTE $00, $00, $00, $20, $20, $20, $20, $40, $40, $40, $40, $40, $60, $60, $60, $60 + !BYTE $00, $00, $20, $20, $20, $20, $40, $40, $40, $40, $60, $60, $60, $60, $80, $80 + !BYTE $00, $00, $20, $20, $20, $20, $40, $40, $40, $60, $60, $60, $60, $80, $80, $80 + !BYTE $00, $00, $20, $20, $20, $40, $40, $40, $60, $60, $60, $60, $80, $80, $80, $A0 + !BYTE $00, $00, $20, $20, $20, $40, $40, $40, $60, $60, $60, $80, $80, $80, $A0, $A0 + !BYTE $00, $00, $20, $20, $40, $40, $40, $60, $60, $60, $80, $80, $A0, $A0, $A0, $C0 + !BYTE $00, $00, $20, $20, $40, $40, $40, $60, $60, $80, $80, $80, $A0, $A0, $C0, $C0 + !BYTE $00, $00, $20, $20, $40, $40, $60, $60, $80, $80, $80, $A0, $A0, $C0, $C0, $E0 + !BYTE $00, $00, $20, $20, $40, $40, $60, $60, $80, $80, $A0, $A0, $C0, $C0, $E0, $E0 +LFOTBL !SOURCE "lfotbl.s" + !ALIGN 63,0 +PWM1 BIT SPEAKER ; 3, 4 + CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 + !ALIGN 63,0 +PWM2 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + BIT SPEAKER ; 3, 4 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,62 + !ALIGN 63,0 +PWM3 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + BIT SPEAKER ; 3, 4 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 + !ALIGN 63,0 +PWM4 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + BIT SPEAKER ; 3, 4 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 + !ALIGN 63,0 +PWM5 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + BIT SPEAKER ; 3, 4 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 + !ALIGN 63,0 +PWM6 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + BIT SPEAKER ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 + !ALIGN 63,0 +PWM7 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + BIT SPEAKER ; 3, 4 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 + !ALIGN 63,0 +PWM8 CLC ; 1, 2 + LDA LFOPOSL ; 2, 3 + ADC LFO ; 2, 3 + STA LFOPOSL ; 2, 3 + TYA ; 1, 2 + ADC #$00 ; 2, 2 + AND #$1F ; 2, 2 + TAY ; 1, 2 + TXA ; 1, 2 + ORA (LFOPTR),Y ; 2, 5 + STA *+4 ; 3, 4 + LDA MUL4X4 ; 3, 4 + ASL ; 1, 2 + STA SPKRPWM+1 ; 3, 4 + LDA #>PWM1 ; 2, 2 + ADC #$00 ; 2, 2 + STA SPKRPWM+2 ; 3, 4 + LDA HFO ; 2, 3 + STA HFOCNT ; 2, 3 + BIT SPEAKER ; 3, 4 + JMP PWMSND ; 3, 3 + ;------ + ;43,61 diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla new file mode 100755 index 0000000..3b43142 --- /dev/null +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -0,0 +1,267 @@ +const inbuff = $200 +const freemem = $0002 +const FALSE = 0 +const TRUE = !FALSE +// +// System variables. +// +word heap +// +// Periods of scale in second octave +// +byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 99, 93, 88, 83, 78 +// +// Key mapping to note +// +byte keytone[] = 'A','S','E','D','R','F','G','Y','H','U','J','I','K','L' +// +// Which octave are we in +// +byte octave = 1 +// +// FLO period and waveform +// +byte LFO, LFOmap +// +// Note duration +// +byte duration = 22 +// +// Envelope parameters +// +byte atkLen = 2 +byte dcyLen = 0 +byte susLen = 4 +byte relLen = 16 +word atkRate = $07FF +word dcyRate = $0000 +word relRate = $00FF +// +// Import utility routines +// +include "util.pla" +// +// Clear viewport to white +// +def clearWin + byte i, j + inverse + home + for j = 0 to 3 + for i = 0 to 39; putc(' '); next + next + return gotoxy(0,0) +end +// +// Display LFO bar +// +def showLFO + byte LFObar + + LFObar = (LFO+7)/8 + grcolor(WHITE) + rect(34, 39, 6, 39, FALSE) + if LFObar < 32 + grcolor(ORANGE) + rect(35, 38, 7, 38-LFObar, TRUE) + fin + if LFObar + grcolor(DRKBLU) + rect(35, 38, 39-LFObar, 38, TRUE) + fin + putsxy(36, 0, " ") + gotoxy(36, 0) + puti(LFO) +end +// +// Display LFO waveform +// +def showWaveform + byte i, mapBar + word mapPtr + // + // Get pointer to LFO waveform by calling PWM with zero note + // + envelope(0, 0, 0, 0, atkRate, dcyRate, relRate) + hilopwm(0, LFO, LFOmap) + mapPtr = *0 // Pointer at address 0 + grcolor(WHITE) + rect(0, 33, 6, 39, FALSE) + for i = 0 to 31 + mapBar = ^(mapPtr + i) >> 3 + grcolor(BLACK) + vlin(7, 38-mapBar, i + 1) + grcolor(MAGENTA) + vlin(38 - mapBar, 38, i + 1) + grcolor(PURPLE) + vlin(37-mapBar, 38-mapBar, i + 1) + next + // + // Restore envelope + // + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) +end +// +// Display duration +// +def showDuration + byte left, right + + if duration == 40 + left = 0 + right = 39 + else + left = 19-duration/2 + right = left + duration + fin + grcolor(BLACK) + if left > 0 + rect(0, left-1, 0, 5, TRUE) + fin + if right < 39 + rect(right+1, 39, 0, 5, TRUE) + fin + grcolor(AQUA) + rect(left, right, 0, 5, TRUE) +end +// +// Display octave +// +def showOctave + inverse + putsxy(0, 1, "----------------------------------------") + normal + putsxy(octave*10, 1, "----------") + inverse +end +// +// Recalc envelope parameters +// +def recalcEnv + atkLen = duration/8 + relLen = duration/2 + susLen = duration - atkLen - relLen + atkRate = $0FFF/atkLen + relRate = $0FFF/relLen +end +// +// Main loop +// +def main + byte quit, key, i + + + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + quit = FALSE + repeat + if keypressed + key = toupper(getc) + when key + is $1B // ESC + quit = TRUE + break + is $15 // -> + if octave < 3 + octave++ + showOctave + fin + break + is $08 // <- + if octave > 0 + octave-- + showOctave + fin + break + is '1' + is '2' + is '3' + is '4' + is '5' + is '6' + is '7' + is '8' + LFOmap = key - '1' + showWaveform + break + is '<' + is ',' + LFO-- + showLFO + break + is '>' + is '.' + LFO++ + showLFO + break + is '+' + is $0B // UP + if duration < 40 + duration++ + recalcEnv + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + showDuration + fin + break + is '-' + is $0A // DOWN + if duration > 2 + duration-- + recalcEnv + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + showDuration + fin + break + otherwise + for i = 0 to 13 + if keytone[i] == key + if LFO == 0 + hilopwm(scale[i]>>octave, LFO, 0) + else + hilopwm(scale[i]>>octave, LFO, LFOmap) + fin + break + fin + next + wend + fin + //LFO = pdl(0) + until quit +end +// +// Get heap start. +// +heap = *freemem +call($FDED, $8D, 0, 0, 0) +call($FDED, $91, 0, 0, 0)// CTRL-Q = turn off 80 column +call($FDED, $8D, 0, 0, 0) +^$C000 = 0 // Turn off 80STORE +grmode +clearview +showDuration +showWaveform +showLFO +putsxy(8, 0, "OSCILLATION OVERTHRUSTER") +normal +putsxy(2, 0, "1..8") +gotoxy(34, 0); putc('<') +gotoxy(39, 0); putc('>') +gotoxy(6, 3); putc('-') +gotoxy(32, 3); putc('+') +inverse +showOctave +normal +putsxy(0, 2, "<-") +putsxy(38, 2, "->") +inverse +putsxy(11, 3, "A S D F G H J K L") +normal +gotoxy(14, 2); putc('E') +gotoxy(16, 2); putc('R') +gotoxy(20, 2); putc('Y') +gotoxy(22, 2); putc('U') +gotoxy(24, 2); putc('I') +inverse +main +normal +textmode +done diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po new file mode 100755 index 0000000000000000000000000000000000000000..8578bcef5d8528894497e6f51c9d9539729f53cd GIT binary patch literal 143360 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%0A(+hr{UiPb^pE%#&_Ci|K>vt;0sSNX z1@w>j7tlZAUqJtee*yg?{sr`p_!rPW;$J}jh<^e7BmM>SkN6kRKjL3N|M{YF9{3;e zKj44F|A7Ay{{#L<{15ma@ju{y#Q%W*5&r}JNBj@?AMronf5iWQ{}KNK{zv=|_#g2< z;D5ybfd3Ky1OER^GMo?jhxjMRKg2&l{vrMe@(=M(kbj7Og8W1L6XYM_pCJDb{{;Dm z_$SCe#6Lm)A^r*S5Ajcse~5pA{6qW` zKg7R5{~`Vj`VaAM(0_=3gZ|^9-W5RqBmNKiAMtD^grVNp#Ks72mO!u zKj?qN|3UvF{tx;e@qf_&i2sBBNBkf3KjQzO{}KNO{g3!R=>NkpR|LR6h<^nBLHr}| z58@wze-Qr&{Db&M;2*?40{r3kH9~Oe+2$P{3GxW;va#35dR4LgZM|_AH+Wb z{~-Pm_-8p$4DcV~KY{-c{|Wqu_)p+J#D4<+A^sEi5AmPCe~AAC{zLpH@E_tof&UQy z3H*onPvAeqe**s@{uB5Q@t?qdi2nrsdmvsb1pY<*EATJkUx9xS{|fwz_*dXx#J>Xn zBK{Tl7xAyazleVY{zd#N@Gs(DfqxPI3jB-sSKwd7zXJav{uTHa@vp$YY&S*({Ezrw z;D5yb0{9{{{X>{4el7;(vkv5&sK*MEo!CKjMFZ{}KNSIzap{@IT^z zf&UTz3qC~rFYy1o9T*D#7kiRem6{ob(uAL+AS z4F5+ziAVzf$ET8I68JyvNiIv^|9D+GUkd-nZTb)Xk53{tM!^3uME0Bv{*N}IGx$G# zjZ{Rz|Ir#XKN|jz(J>cepdZKsAcz0sOk7Mi_&?@!AJY^5k7K|CX^Iu-D@RdcczV`ZJJLEg`TJhz}soS5gJukYVC@DtUvSCAl4-6k*y6X^rz22o~=%7NgX(m%CHN)44W!o4GK0p$uN-3ewNx+uTv{8QSCBn&A%ny(}}z%82*|J zK7B}<(d+eEZS}eGlRur(UOKNmb@|i})t63bPnQ2&`NQuUMui@tkJEG}>&5dG=YQ^e z=1|f1UHRG{&Refsto-rJC2hIYN(E{Ul@uQ_lpOxI7W~iU|BoY(Vi*oac@m8B6ewT> zQ9zn9pHY0gtKiwQqgeX#{GJ^Jqs~6Va(}bFes<|Dt0HFtTUsXIRmNMNC=>E3FIxxa z3+Zvg(p^Op*wjVEXH!{qDr-%kEe5(545FO`6U>zpbZVnSN%!d~1+#+$0^N-*Xs;~b zBrf-Oi=KgAY|Qa{NSj8qS2(^3piqlwR;i6ha(QK2Rdo5ae+inn&9 z9{d&s%28lnx+acNWbYd`haDbij60Cb>QuCef)rV z+R{QjnN?3=)l*sZZ>;Vo#TwQauMldD(R63a3FMunJnG?~%SL`aBc+Zi_UtgkvV(`q zrHUw4vHZwj+K>3)uG9&a_PML7cIas<`K6cXJ6yl%_Nb||@3o_O?p=yrJJ5*I9n{8Q zQ(3tnb$Q;f$vF1hNqreUs9;28E%zfmY#7f{yU`<+HIi~!POyn<)TyWgxr0O3WAIIs zxXSgkWA^eR)En!wYPp4bT9K2dSh3Ui5Y?a&R+TY)+EJY0Z=&5esRh+LXiVhSlz1p* zr^coD{&1zpO5gC`JIE^0)n<>-sg#EXuSjB2xgBTS%)r(o$CFBaLtHK~g85Xm2QB=cHJCvbv!Z&P& zUsrBhSK6O>dq$yKUZ_o6z^tUHhL-Zz|KqbphK zWAqLE7g@#GL&i4^zp&VkOmB!c=e=S!bTj8IGAjlj(&dvd)v2lHwB_H6EH{2QZ5?us zPVOo`-j^>|9Nm>a%X*cz=@>wnG|SZTtKmi~UOq%Sh_UJ)*)+|sMuAS0L}Nj^si(QC zsUeY6BD1=i*-*(2;pwSaNi99i&GBZVyNYutCLY$vD{0qk8rzdpem;}>^G?OZ zy{V3!e;!h*b}C!c%UssWoEPMg2B342xrPpt`WKdZc$w9;VkjAEn!1Kn(u`JSS$h!~ zsh?+mr`UW@W9ph+A@&1tEh?r5i=Jnx@3cKaOw04ERiu+sCy4Qs^;KLX2qAkP?clE7 z5qgPU-ki+t9l=GZxCj*|rr}RryW_wNcF4Ni_voT!25XI^G8OH+jKx%gG9?GhPh1~w zm6eIW{DL&&TH1A|k*XLrg_ZZGZVFG0;D!@B?j<@3>eQN@X!jIWr?!qrF-&HoiTb4l zBO-*AS=>Wu^nAZlBdoot7Q+iH7ZZM#8cMK%*o%6#c1Ic&Cg>C^{Ol3RyCw87qhijT zAKWlvpL@r!iR|$A=qpFX!yn=l=ccpP-UVy!tRl561K*`+aiyNl;)%-9sfx?lBMM6d z#lszH-YzSXJ%WUlVP&y8i8ZV$RzJ&H`_bMTBdopX`+Fm-aobWa{&Vw0)+!_^rP9sF zZr?@)fV;O@kD!rzNR;h+zu<3*LCv&v2;m&{j-=G8f9h^o`62$_X5Gx}QIBV7+-Ri1 z2sBVMvdWz2s6l0K6mL&r>#ly^%SyXV?uw8XmV8~xMILyb-Ol4<%I_%4j+Gi|TMBISl%%YuE25fu zYePM4uAKV%O(<|S4;(K)Hh7@T%Aerxt2<$o8f#sK{v0Pl4uSjng<#}Pp?|W zAb;(hHOqKsub7OX%(YZR!FyCh_G;{3Ww>F=UeiD{Z=#2PH5IH{##7gt3YIm9v&R>_ z)4*g;C|It(W-?qgoxN_-jBmbTQrA#b%~ws$HKysoW&E=>CfakZ2DgnO!*x@rEXDTS z`&KA?T4SW*$=&oWm8{vXi=rH;^b~{F#@=%WoeVFR!C* zQpcaYYSLUj`>Toeg*ETioTF`&6w2L35AACZx)q6AV%*{@6Lf;58zhT0Zl~ltjZZO_lI-WXlhK>{TT@_wNWwK?WPzi#&6G(E^n6k$hE}OE) z(f1%nXN@hoVyZthI(IBKG#z($OqI1=iQY<@YfK3%>9H}YL*uhYtC9*)7S>@m&XQ=Qps z3RY*2&K_Iv-ks6vW=z`{b&E-{cn^Jbk{(dsG%5D%AzC*)-zA({l|A9rZ1UtnpoOZ0}iRBST%SZdF+*=zBvNa4)a^rw|Le%Zbi2^!IVBw7CL2?<>H zE)u#$G<*GwBCsd5Xb)|?dCimnQhkDi1?Bx4aW)ch-sOHHx`;h25ODV3RWiFS*E^i!kn$T^N#wCiKeY!Ipy6o6|A6)d!~Zb&CMnv5K!5;f|a-! zU9bxCPEugw9?Y?Xjs;`Y4W_%}XgknG;`F3DW7YRD$n~Z>Z{5xt=H{ zOp`Yd#b*WDK86+iqLp~p@Bx3w$;y+QNT*lx`1u31 z!^&Ra&rr+FWefQ!Lk6g0&1qzu4jmH9Jy02K?5U11%T~si>0pR8a}tBxT)9LOzb&aj zT$nE{n^THjQG1nTukusM77;eB97}tCD-!nULbuW=BLSO$%cNBIVA|zQMMcnURZ)zY zzDij3Xt;!?7_-%;Gf-*UMSK-iMUZ9OzJz5<=&du#lp(Q-NB5;clSCLROKF!bG3wRr zrC()Eq**O9D;DiDM4Kaw$T!H$(UIopC^KzNmrviORY#i@cl3`(o0I5~2AM`o87(q% z72Vcp^Iy#4@o6(TB|)q?tWKd8nsrjO$gCKmhsiLJ_7i=K6QoWnRFs&EZou3~!z9)! zR_ydcJ2L9|tomhEonWS2;|yb2^&6~V9IO5dOZ0WiR5Y8dug?*g4RcxUb=mOOsZePO zUC2ecA4!Cy4dzlRhY`lz`d#G{gw`f%o~qJiQVV8K1GJ3dF}-RtK{6iIQPRu2J)N(T zyQ&l^daG3PE|oIFIFj0Bn8Q|ztW za^;m$W0~PEELTjx<|wsc$iNv~1V)Aa6hBF+NjA)5hX}c64fCmW5xB46(&R&FB&R>Y ziQvQN4VW$DdKt0hR4+3PoQ@YwV@R!hzR)TORjJk|ZEU~hexiVR=lN(<@(94|D%Uq=z9#N8D&Py<-<`vRj zYN1myCkQWN=p(sjDtmHIR!X_Y4C(yBgq1vg`1Jwgb_ue_?gPXrjlL*^-8mAp$CZjx%O-mNA#g=$S*X?H#>FIDEQs zGQm8|ZWGrVRXl@RX54z*IHc=VKEFw7=A>mZvo)d0YC8~Nrqk^USg<`klb|FTOkMGv zmf0>dpRou?i%@|!u7S$RXADwvWh_@KTPZac(rXL(r82AZOnsfe+Qx}mq-N_iT})Cl z-7K+{sNZ2j_w2eI z;$FH>_XL&E2}&C2(C0k)Ll)Pc6`HwLW#w>**{9ub7{~I%x2HcVTV<3?8K!cY4_!JDl1@a-nfgpol43xI(UrR0sEFH3((M;hQKPA9!&*h+fudhb z8`c_ED3<=BNZ+etxE@sWWVkrMtUVR|4j5I%Z?`&A5)baBD3gKa+Q+EM8 z-AaZ*4ZHFTOMN0k;WE3jlBJFq`KQ+EVvHAx&aejviTMs1Pb*vpjpd5;14Rqj0}I#< z#;k+Nq=L7bOIX4YY0af<_Bhel1a8W{w+qrXjLsgTRG=b}5NMo~S8J4lxFDV}QC86NkWx?#?f}QkRlAzQi>ijg0>SC5$%Ewu1 zWC5!#K@0b>>QYv*)L@*hm z?&w8qLE65z&z7=QNmB`%VC5-uN>FI(q+)uJ>eGg^MBCtDr2pDZFJ5acJp_v&XT%@C8GrMHbZyPC?eL@l~W$cTf=d7$k+%Tbt3hp zV!GD-5Ph5tUtu7GNme0V)15Y+FBrk~Bi)$KH1#rbk!1a%Y3`B{ckufYpyQvpCad_OqU5LR*MN+j!v5s%;rV|s$f3C>rQA{XGP_C#U z5uYyxHPja^U=J*0sodf6q7wE%Y3C56P)<$_yZJIZ>}7ThF+MQ}eKMH_Y;!4_Rj?0ezHdCs>nt0FEaUQ_&|INp&w2{${H{%dO3js5I`~)hbbLcCI^3)#euaIuNsZ9 z2ZUxKo$VtTqMPlb7$q{J=sYiurTjcO`8pP`1lkv}#K}yhMbpC&JfAi8&}fo}@(ZJ_ zQK!d}F{-5N%bZ&$AgT(B#-+3Xvb37T?=GXTg%%kYM)wFc6}~{UNHoJLpn*4vK$CAN zN)H*|0Cf*Oq}UA_?{e~muMFMI(LKzKjpUazK1{5~iOw$L6NJ3Dm+q5eliZpzU?>^+ zHjSc2UC>$`;%^l6@*$%nTuR8Q$mbn+jjuas;WWZLhF`yJ2<`vN*NQ?G24$S7KgaN` zZ6Vu3sY?LvF%uzS`H65)2>p~0;-MWE>IvHD4icI{2MW;Mk>vIvOhWTnRLYXsK(>OJ zEh=NR5973i7{bh^7)sgZGFG3al~X2hGA}>&fQhvbN#+!jxA?Geq;4VTCFDJPRNd)4 z3_D%>&>Gq&{JeNGmd)r6k9?Xm;UuW5Sh7|jt2jZ?J8W80F>4+4*m0J7kgRg`c{c1M zKLf!RWw5g3og|kybw~+qrjrrsBQIzN6?6av{?yH^kri(4X>O@x>3>ziaLLMev&Lm? zC$pRe1pH|19d1%Qc}-!Xah&;FchczRdYF|fX0eJdj~a&#o5{)tV%T8#hg%tbS7i8+ zwSJaDDwMnfy6#EJu!+9>2q9jQE5fjrRd~op6M7e&2s;M`6>gHrR^BqDz`Y;Jx zsBWG5XI589uR)#&IH}^R?=`g7^kI^@lSt;07LZ4(XR>6xIZcWl-z$y4>O*)|DXq3> zI>j@?MTIgs5e7oqwf>-#;xc+Lx*QsLlEQ-l$xxM?q^XkKyf`dyrwhrz6cU4I26C6X zv|o{uJ+PR~*~jLTvYQLo%_SlIXQDAX`wnY05K`$z{Ww4(>d)n29KY$L1Id3H6AXAP z$0IB69rZLgVCc!bRt!>}%hUpw3MD-u^XO@8-a_+`b%mAvHGEw^k_n4hIP8@yIqd68 z()n~yogQtq(-?&YLR6?spj}WDRZX@A5oy1a$(v;_3U_<@GS}%&in~vxe}98kVx^H(A45ta{0RToVZM z`R_Dm9AtQtjb6eg(3bI`1(@!1-N4}8B{(i&jlV&I8iFRm(gwz?jwFU9mjzkmzcbm) zx7bxn$#&56N+4MN=^5zJ5D;%OCKN@Rt=-0lfVq(Ducd7CTdegQ$stnB=))}ZA;cHx z#w3OHm~mYGI&Eu+qPT8Eenf=US1hf@`MN}`(C|oDZN9?h5YvQ27S=jK>|+$sgia#2M6&?N3T8abJw?R(>WMf`E&Gsxrq1fVuy zH7c~kl}7wRl)H^Mg-ADyf_|b&v`T0`EBP9c!g}0jN`3w~$@w4Iya@8JxN@S+IWcB! z0vSW(fO$M74|Tq1Xj%K9t0XQE@w3EW^RFR3}&tf#`8W6Xt{ z5?0b+pJBJHBwaz;tcqO*WUS+p@K+yYbrrOc7o%ob^$AvOVb$dzY|8$D2zx~myJ9r^ z#E#M(!~gl-x7NJ(zWpvwd*I;Fqo)rX_}7K%>e|}Vp_HDHxjrjc6BVl6NqzO1f;ErDFMW2Rs_*xgpPNJ5xz3(Gb>VZVFHW3HyTQ(# z^4!8HlP1ocnEK+h7iUeG`SR@PbEhl_Z8SS~%2e8Wb?%F^r_7xA!j$J`&zqV0;-u#% zrA(YY^TDa9^X8<`X0(%My*Ot&cENq|g%@Yen*AW{);e|if=RTw;gpH9sJO{FhvSSg z<33}G_6y^M{m&HT9*#V)+faC9>anW_o-1-04(^Zm{vSuwM@Jv*cRcO*ONO0>69$dp zkl~XfdgFnEncu&(KRG=)eX9_w{Bcn{J5RzB@`R6dA2=sMD6&V}c~Lwj^c_3lz)6pF zkEVOMLIM583AfVkKmkuU@wq9fb0$xnJ)a6v$b~{akCBSvdk-8m_{nFJrvy6!exH|% z6$@J*=+pbi&xekcS5Ux)wYmRm2LEx%G#eXgqdr}F9_e?DbB|HGwo=YOd<^@I7`d2L1crBm$S zN0TQ$H)-;esnb$uca;}r&YCk{Ae2W%#ZxqNw}`lC5nt9lGDQ#O!c0bP(avq*eXK}c#q{4aa{eUdiAN_^jAxRkKlAoXv9+&E^kV4dBHDqn zXXwnjWOxTNtg8GoTq%QxG=pxN_H#RKCI4;EP2HAZlQ`+Iin>Jyo~xKJeSE>Kz5_&k z1q}!882-U2OYz`HvG7jKy7_DGg@Ob^Yc&FTNq^`B&arZvNUP znP}z)amGmjCo1J1%Bd>)t8oywsjd1K z=FY|^okQfqNSUwk@c*R$-3X-052R-AOZ_KH>!7KdcQIU`WyhcY>+^5dT%b>2QSs}= zC{GM7{C`Nj%;|h}Hk%_b4;i2@TV1T)z!nM2Wauy(SR+rFA7A@wDJLSgRera!)unVR zNy$ihnSbc2g4fH;M;S~nb5~a95jGMd2xSYHba2WiMcMJl$!p0sdM>XbQ&^!EHv3IFr+-(dve zRTcblA^xyQqhhogX3OUyUIrsqRcn-tMO%R($joAx{LolrGKyfN#!^TdR$TJFCZNBm zk_LR&8D@XAzFL1-pUtfK;zU(A{xkIapMTP8iZ1DEN*($deQjfP(KmH@>3)5!x3{W7 zTE6~9FqcVJRcJN&b6+Xf&emIH8fn(1a_tHg!w?T-Rt%=1v=gK#@SmAl`n^3mq%181 z=-fh&__fqZy3rN?N!i2!e@b-@_EOP>(sX@Iu$t<3wAQw6tq-*JQ)Myb!mPqvl}6>% zYS_g*i!_5_o}|A)qW&{YXf_Bp zS(w|I$#vnLSWq=nhLWHe`t^-DMPo;jJpWT|MT*sl1`Wy@ErT(x@5U*COi?fZZG z;KPqXul&!?f1eQu(;0SJ4F6eUXV1fb+K3CewDWxGr$k9iPVzVj!#t6pSj=+=OI;nU zjxqD})k7ysUrNkkJ{(W?C|SmbCBd5Ap-U!tyik?PBohZ{w3NfoGIz!QQu+L3DWhQ0 zLr?xr^+Hf9k`#;`PW~t8sAAloesP(9Sgswz8#>P&3`2zIMvcdGU@k}&ilRR)RN95>^z3r)|F|QW(KrkWNE9i81;(9 zg2|RZ@Ont9F$~9N3Kuinm*6&rT0v5VYR&TVI>KC;tF@#v%uZz#W4#$3B@~sV%E~OK zzy7?fG8QtK8CuHHGTN-nEdEZW0#bz0STaze_EU^Q68&QicBd}r`%zw2=9*x2@B==h z;spNiIEBC=!{D7Pt%XKpB8_?m#_jjiL2dkhP1Dg%A@!E?et8vOkh8ek)X7` z6kRXOORv6P+w!n#Grv6ZhCY{ivLj#f!1BWsaQV`7SG*j+8PMXsXS zmW_qAUbE__$>q{*=^B#%3n<*{GVOE!O*#{CFR`w;qAo?1CETj7&PgCD>`E3oA%RS~ z5IKHkjeu&-RML!F=nQeci2ubllT2dx89eu2B>pA7WfRYmp)JqaxHnhD6|U22m`g#C zHlwaz=DqBlGz&~lmUL@oZlU$}*DLC~XzUVEA+;oui>zR>*iQMc?27;GG8DSn-E~Zt zb{0jvDGZ&?nh+}S!%u0NnGZ#uNtll7t+l=r!4UV6X5YkP`liveQ<_CI2QJ{&%Xs|p7JcCpdWVp4sOK1K6tPQ7yz*tZ2bOdSeFXn&-Aq^fFFn%LQ#_t14093A z|BF=f1ZAo$;>JE1)(!e~QMq;Q6OPXoKRS>8GW=D#<^RHszah{6<5i3M0`)rF7R&zX z#*NH1eV~p;vNQfy16*OrVD_qL7Qz3S%y95EpSPil|Ft2W^Y%ia#XME6dsB5flYEev zi^-L8CxUulj&(y7t#L_Ey~%mS>i0bJH1>U8`Byqq1B(xqJEM1Xb1-<#pYO z|93MLH?I$680+Jq(lWV_$h$;2l$3FqjJ7X`yO2g9na6a+|58rkf6#oKtFih-4dFkR zx3;CG$iZG`w-(p77*&_PEmv7jV28~uBu1G#>>5yr~oUAAQ?~MNq>A!RyAJ3q9a-94*5pP&S$hD@?LA2BM z<*iL?cjujXZTW!YYP~_P`v<4rT3lU7{6`!(>+vxE(oCeqQT<4B1&k_#S(}jz${_hj z^=D>T6vA-)FQZ7tLkwn?k|Oj=Ka)F89)VBxgOfp3wNmy>@3Q-}hY~U#;KD z@-neIpXIX-l6W-wT`7}MPKzZPK>f6-aPUMnV-J4AWiVawzZt5E^l~l3Y$5(nKS`FA zis&Z9{~5&pcvEAfe_AUf579A?v8;OHeJb{Gk|Bi^@owMZ6OaUXB$FwJ%pUwuA3M{9 zT@2gFl-jO5j>_ta|Lw~AKOKdtEJ1lDpRwwJk_Vv^AI6fvKb4FQCIx$f2x;rcx!_-Cda{=U~NlvQO*6lx&R@8 zrK$?5zdSULbG4fIQ~S!bn!i`%XQ?U%pVkhhHf1o|^Ff1aK_zruw?3b$DW@E27s*uG zdjoei)7V%tn6CI=qCd(^578@~P+J{rZDY*|hIs#aQT2XTXCtXKroFaVcA3)xzAlF*)W!+mFkMv>!Ovi~G!QE#q!2xwaPcXQ# zW1WO)>ZH~D5Vwb3{E*sWQI#>wC*X^^qHCLo|LeNqf62uhdP*Lyq)QHj%;|8}IMfA)sxLZRDWWt$H{BO9n|GVGh zRi84D?T02^WSFNXnYJ>yMo(+-{s)hr;=a*_8kaV0Bh*fomh6no5YJnJMD28zPdb=r zg!Gd>o8(|u{4enpX|*u_(=%F&HY*DJUrv3fpi-zG_{YGDLWxFj?em+eGr@;+87Jg| z!H>~zs$H=TPq6q2C5$*z7n|YdWop9mC!EjJogk3Z8UNdv^{0d4Pv?J}UQtz${>@0| z)_tS8q}Awqe_pP&Zpt+(R8l>0Vm;B{L>{9(5PCyPwC?6vNbN8cA5+ULmPG%-^vn?d zldZ#SV3@A>-#=>TJgalD)%Q=8UeLQrq5rFk@(LaL+WX{xiV5+*dzWh1ZcX8950q>F zw#kz4lS+E4T-#lBNpI0#(kf^K7gIqr$MCnLGZ|Y#qY%ouDcMg0w>iqak;b+w{+Avk zd^x$Zayn?q|5RFYFx^{yKd;oWKhU_VzFL31pK%q*#{Y&tFSNtz! zG1LV`=tw{5IHA-f4@fslalW_@j2WhJF>fthC9~OkH`N7KwYq|>*Y^|th4kasj^Qym zRA)t+geecz8m7i_vdC#{=wBAIK?^0ukL`;8rA$7Rn@&ec$?22BCp0RZsjF>X(yvr_ zdEvVJcWcrpl@+&&1lj-e9LFu=oL4!miR3^2PlDCpG%SwDJ#VP!wGva zh5ux_;(tT8{x5$n4OkN@r>>k>GR?Y5q-EspVD)FO?H4hhDXABfCTW|vRb+=x~Vb(0~ zLA|s{{RgY})4bM+=>A&R9%KN8Q@A$2K;sUbWoj}lop;=S7cpJ&znxisI$ZwK`5&hu zRTkObWbsp9CTlf`Z|P5JD~4(ap;Qb$rA<|(r)N*pR@0x_B7Hc8Cb^u+7ZUm;Z!gV; zsw0-iWW1R!V@UrqM9W?Azkk%wc}DzK%T}8*ifUTEA^q>_s3rXy@IIs>KX2wqUT$HY zO0Ly>m9f&IP2O8RI7^ixJEc{quAR^%ULd)|d`#tsX|F#qHZyA&)gJbnr1665)-#*z zg?Tg+UGcx2wf=EPzy3v_wdRZTB8Ta^J9yGnzp;)y5v5E#@xNB0%~b*aSXWUkdS0C+ z|Bi*mga=#=J9{enPe&vT%UE|{=II{MoLfRtm^csoPrnpP7mEK4A@9U=hMF4Ey+jKC zmVm$+X5FLVY$6DT*(*XGtE%?p4nI+okD5DEPDoAAbpUmSEMnZrs{4@!WdNNiNorI5 z9R4(!LKEgtt^9O_FjPO?#*l>)O=ET^RiCYh%i4gD2Lp z#QTK*X+!H1BEZi~W;~Tb4Yd#@&>7J)dEr0>`s&7P?IprV<*{Ayzf`O=B!TFJQeyZ( zzoA;`s0hgiW-a;;?-xdXRfb~}b9MK;%(ye;QYt0?-%!%9en^=$y9w!plgdJ^AfIC< z`i)ecPHp1TxTyLwUGcx68~^@8&;1uk@d3XsG`z(ZsB!vPWth)Gr_)va`|F3IFViI>zNi;s1{EW`` z`zA@4d~&H>rcq>6TQkW4x{5RlMuxns^b`!9u0(H>>{D*kVmAIr_BS^&UGcwveqh zrm))EOO;he{7>s2ByqIXp&I><$;_Bjn=0hngcdD%0XJDxQ;eFSoz_27L9SLUS(+80 z77-dz<(heV(*NtTRCXe+uJ~WlbTpY^8V|K4oqRaK>P?KfJort0P5O1MP<#D;4a*EB z{#RtBQ~le>?jZ@vq`p>XN&h)p$7uF2o3erVGc&3}Wl+T=nd z2=V_VL09}Qqo8?Xcr?f1gwgsBNkO3-l+lAxGR&Fi5M9}Ky-EaR`MBoSqEn5*#j=++ z#nBTqzJ*gFq2noOi6*pI1H(m@Hq3{gkleFUF15zp75|Ic<$RvBliw9|Hzp#RVcWu_&a+K@vn$r-?O#s4yd22U{VV8)kq z^l3`}33{0cp78THL0#}i+@RL_=^wrMv6``Lr2c4|(8=-SSt7n#6I}fFbwepPh*_c( zvUn^w3-O#q8O$K$0ebA>L5@cly(|7#PM%}fmDQUxh1Gj3`ie7I|Es+-0j{b#z+=bYa;-`#R^e#zS# z)zp=;wcHr5lJn~NR5{jn#z$Os@0Tk|&zF*wgO`*^5k)lz6YbVqdmAb*kH|!o9ZB*; z`rLk;)*!fw>?+0WH|&QFrCssv|2_4t`>cHDl#c!Ht#3&jUekW^&;j4BSb6K-_I1st z?f)N$*Y$1d_FBB#IrHV{qXL$bUI1o6yPL`?x!U z3guPl3gw9Gy_U!2iR8a`|F4&N^6sg9uKmJ!2%dIs6#WXhrCi!nI=-@IW6f>VjrAuJ z>)S4u>g<>l*mBgpx zE2Zsm`3+tnnkLIo@b3SWKA2S2I@8^7PPD{UNI@@n}n*Kj5n2SiuXQ}D4SO? zp=@5z{i<@LGO6OzZHjUu&Sm3u$@2GyDaCeQ;}d1l$>q*R<*`|ap*r*AnY8-bI!%;2 z3cUM&*Z461e?Rqn74!eEQCFy#|Nm+YbHK;cPqZ&I%>VzSzEa2h|92ZR4b1<4lex&m z{Qsr?y?)I9zug)a!2JKE!I2@%|35XnJA(QDf0}VY7Uut7o86j+`Tv*Y_w~Vl@Um}? z5B`G!RaN0Xn5Irr;Xep#ng;*D0u6J($9)6!>vi}KQjM4a|G`efG~qw^v)SDb|3N2f ztOftU=s++C|3P6W9EShk>d4}B_z%>~oNV|HR_5%D!hf*6V4@HHhvUB8KKLK*P_I+r zfA~;+TZRAOHf^{D|HCm2bHGP^3-uRt_#f^tDh>D_2AU-%{0~F?v;FWtR9c5E%pZI> zFh2A`SkFK|1DuuTML!`waLmUN?3b@Lw!7KQ!ULSnby=_%DuHV*>DBObGT2 z!GAG0{HqB37c|?_Jk>>B~$9#!V>mCdKkCB000nC$lAh;le`Gi}- z+as7C@tln3GvWWZAbV^s=0*H@v?&Jv$A?`CRrpVySL;;xPYN|%ga71d?QsqMlRo-6 zI{YW^>zD(+q|@WZJOlod+s!Hy{*&MMAM?Y1GTwUAg8yVwU_cQ5li{KCF#IRiM24or zf3hN@Ul#l)Z)L~w;6M31I;AuGC$Dt9PKE!aUEQF<|MF|?G7bKh9ol9M^|@Ccsl)%0 zX^9(kdDeW>g#Trs{{uh#FPp7`0Q@hVgY$#%zpM>C7>57l<;Wk>;eRF^&N()a4{A3beg4)|!w-I8zc z9}V%}Tr=eU%OW(d^vZeE5&_ z*uJjt9~E_PRpEacr47>HfBH<@s=@y>PQO)$|0&(j4EUcm8khsVEcsD$jtT$M{r-AC z{7)0Dmo508UI_Su=)YKKaR~mWw(wIC_@DNrhce-Rs?EAM2mYr$xuf&pf4VhxZ6W+m zjotUC@L!c_H*4@;CA7b2@Lx^UOLX|J&NaFi@L#nXm;-)y(lh2N6aK4d{uO@sujW|W zEcmZl1HFUrUtJk`I|TpL$?%p4{8zadS7gF}wJvK+4*XYL^PbCx|7vk;P9gkP9o-M9 z@P9oj^Yz02W$6bs_`jagYjya)E;D{&!2k87fjQv&C#^N#GU5MP(a4?%{9k=DZp(!K>!YkEa^U|OoVOz%{;&6At%dM^{jA3c75=j) zv~e2zXW9A*4gRym`g9%svw_BC2K;9o2IhdDuWT{jGvPmb(ckKa|E$S6Zoz+cJaA(W z{l$PSxn%F(Ys-?Mv1+tw}3>sGH^*0^Z?+*vcGKQ^_t=8>w(ib)9hZ-z%|YNtLn zea5W0^A|NPTe*5&^Omh`J9h8+{OhBMe^I`o_~kUYhjO7(qzsXJ3Pvd<%I}m}%2GLy zc?V*7nW6pSq+v;ANlTO3lk$^CCBK6AA3-e|RiR=u1}X1FJh$ z8w0CPs1xFHv{rSz>f?r_&atANBV^ivix#E5&@pvr(KWHD7ZyF&yQwZFlYRZO_#vNJ zcxi7=Y||g*dd1ycG&+1CJ%-i zrW<}YEH?sf1l^I#jeIu>+=!hO-uvF?yzhDI z@z(2=gB9Pp{ryJG^!|%`7dK@#>-H^8b!NDCCWMFAu!D@bbjV8!wN%yz=tQ z%R4U*y}b1D)XQ5hkG;J1^87zQ?ycgxmtH|kzXkcX0!lAe;OlC+Y)xw(?m(Wqp4K|w55Aj@b}-pS3C-^nNB zbMk5V4!$aDz>2U!tk^EWF3T>}F5jt&TQ9eJ+&X(r@SSSbX>C0df``Uip25$1@!iP1 zcmLf!#rIJHibkbSN7NYAM@!Hsv=1#slhJlS0FAS7d%OW0#DN^l1-gx0xZC6fJ>WZm z=h*Jzci7(Iv-l3ai*;aK*si)A@((?Nx}Z*|8|sL;^{Q{?F-+C@5res4#iR!(1>-Wg6;I2~bk zgWU&C2iSw%9qCdxhq}Z3EaEouQ_# hilopwm.a + acme -o $(HILOPWM) pwmvm.s diff --git a/src/samplesrc/a2pwm/pwmvm.s b/src/samplesrc/a2pwm/pwmvm.s new file mode 100755 index 0000000..c3c11a0 --- /dev/null +++ b/src/samplesrc/a2pwm/pwmvm.s @@ -0,0 +1,1007 @@ +;********************************************************** +;* +;* STAND-ALONE PLASMA INTERPETER +;* +;* SYSTEM ROUTINES AND LOCATIONS +;* +;********************************************************** +;* +;* VM ZERO PAGE LOCATIONS +;* +SRC = $02 +SRCL = SRC +SRCH = SRC+1 +DST = SRC+2 +DSTL = DST +DSTH = DST+1 +ESTKSZ = $20 +ESTK = $C0 +ESTKL = ESTK +ESTKH = ESTK+ESTKSZ/2 +VMZP = ESTK+ESTKSZ +ESP = VMZP +DVSIGN = VMZP +IFP = ESP+1 +IFPL = IFP +IFPH = IFP+1 +PP = IFP+2 +PPL = PP +PPH = PP+1 +IPY = PP+2 +TMP = IPY+1 +TMPL = TMP +TMPH = TMP+1 +NPARMS = TMPL +FRMSZ = TMPH +DROP = $EF +NEXTOP = $F0 +FETCHOP = NEXTOP+3 +IP = FETCHOP+1 +IPL = IP +IPH = IPL+1 +OPIDX = FETCHOP+6 +OPPAGE = OPIDX+1 +;* +;* BASIC.SYSTEM ZERO PAGE LOCATIONS +;* +HIMEM = $73 +;* +;* INTERPRETER INSTRUCTION POINTER INCREMENT MACRO +;* + !MACRO INC_IP { + INY + BNE *+4 + INC IPH + } +;* +;* INTERPRETER HEADER+INITIALIZATION +;* + *= $2000 + STY IFPL ; INIT FRAME POINTER + LDA #$BF + STA IFPH + LDA #SEGEND + STA SRCH + LDA #$4C + CMP $BE00 ; CHECK FOR BASIC.SYSTEM + BNE + + CMP $BE03 + BNE + + LDA HIMEM + STA IFPL + LDA HIMEM+1 + STA IFPH + LDX #$00 ; SAVE PAGE ZERO +- LDA $00,X + STA ZPSAVE,X + INX + BNE - + JSR VMINIT + LDX #$00 ; RESTORE ZP +- LDA ZPSAVE,X + STA $00,X + INX + BNE - + RTS ++ LDX #$FE + TXS + JSR VMINIT + JSR $BF00 + !BYTE $65 + !WORD EXITTBL +EXITTBL: + !BYTE 4 + !BYTE 0 +;* +;* SYSTEM INTERPRETER ENTRYPOINT +;* +INTERP PLA + CLC + ADC #$01 + STA IPL + PLA + ADC #$00 + STA IPH + LDY #$00 + JMP FETCHOP +;* +;* ENTER INTO USER BYTECODE INTERPRETER +;* +IINTERP PLA + STA TMPL + PLA + STA TMPH + LDY #$02 + LDA (TMP),Y + STA IPH + DEY + LDA (TMP),Y + STA IPL + DEY + JMP FETCHOP +;* +;* MUL TOS-1 BY TOS +;* +MUL STY IPY + LDY #$10 + LDA ESTKL+1,X + EOR #$FF + STA TMPL + LDA ESTKH+1,X + EOR #$FF + STA TMPH + LDA #$00 + STA ESTKL+1,X ; PRODL +; STA ESTKH+1,X ; PRODH +MULLP LSR TMPH ; MULTPLRH + ROR TMPL ; MULTPLRL + BCS + + STA ESTKH+1,X ; PRODH + LDA ESTKL,X ; MULTPLNDL + ADC ESTKL+1,X ; PRODL + STA ESTKL+1,X + LDA ESTKH,X ; MULTPLNDH + ADC ESTKH+1,X ; PRODH ++ ASL ESTKL,X ; MULTPLNDL + ROL ESTKH,X ; MULTPLNDH + DEY + BNE MULLP + STA ESTKH+1,X ; PRODH + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +;* +;* INCREMENT TOS +;* +INCR INC ESTKL,X + BNE INCR1 + INC ESTKH,X +INCR1 JMP NEXTOP +;* +;* DECREMENT TOS +;* +DECR LDA ESTKL,X + BNE DECR1 + DEC ESTKH,X +DECR1 DEC ESTKL,X + JMP NEXTOP +;* +;* BITWISE COMPLIMENT TOS +;* +COMP LDA #$FF + EOR ESTKL,X + STA ESTKL,X + LDA #$FF + EOR ESTKH,X + STA ESTKH,X + JMP NEXTOP +;* +;* DIV TOS-1 BY TOS +;* +DIV JSR _DIV + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS NEG + JMP NEXTOP +;* +;* MOD TOS-1 BY TOS +;* +MOD JSR _DIV + LDA TMPL ; REMNDRL + STA ESTKL,X + LDA TMPH ; REMNDRH + STA ESTKH,X + LDA DVSIGN ; REMAINDER IS SIGN OF DIVIDEND + BMI NEG + JMP NEXTOP +;* +;* NEGATE TOS +;* +NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + JMP NEXTOP +;* +;* INTERNAL DIVIDE ALGORITHM +;* +_NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +_DIV STY IPY + LDY #$11 ; #BITS+1 + LDA #$00 + STA TMPL ; REMNDRL + STA TMPH ; REMNDRH + LDA ESTKH,X + AND #$80 + STA DVSIGN + BPL + + JSR _NEG + INC DVSIGN ++ LDA ESTKH+1,X + BPL + + INX + JSR _NEG + DEX + INC DVSIGN + BNE _DIV1 ++ ORA ESTKL+1,X ; DVDNDL + BEQ _DIVEX +_DIV1 ASL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BCC _DIV1 +_DIVLP ROL TMPL ; REMNDRL + ROL TMPH ; REMNDRH + LDA TMPL ; REMNDRL + CMP ESTKL,X ; DVSRL + LDA TMPH ; REMNDRH + SBC ESTKH,X ; DVSRH + BCC + + STA TMPH ; REMNDRH + LDA TMPL ; REMNDRL + SBC ESTKL,X ; DVSRL + STA TMPL ; REMNDRL + SEC ++ ROL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BNE _DIVLP +_DIVEX INX + LDY IPY + RTS +;* +;* ADD TOS TO TOS-1 +;* +ADD LDA ESTKL,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +;* +;* SUB TOS FROM TOS-1 +;* +SUB LDA ESTKL+1,X + SEC + SBC ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + SBC ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +; +;* +;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 +;* +IDXW LDA ESTKL,X + ASL + ROL ESTKH,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +;* +;* BITWISE AND TOS TO TOS-1 +;* +BAND LDA ESTKL+1,X + AND ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + AND ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +;* +;* INCLUSIVE OR TOS TO TOS-1 +;* +IOR LDA ESTKL+1,X + ORA ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + ORA ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +;* +;* EXLUSIVE OR TOS TO TOS-1 +;* +XOR LDA ESTKL+1,X + EOR ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + EOR ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +;* +;* SHIFT TOS-1 LEFT BY TOS +;* +SHL STY IPY + LDA ESTKL,X + CMP #$08 + BCC SHL1 + LDY ESTKL+1,X + STY ESTKH+1,X + LDY #$00 + STY ESTKL+1,X + SBC #$08 +SHL1 TAY + BEQ SHL3 +SHL2 ASL ESTKL+1,X + ROL ESTKH+1,X + DEY + BNE SHL2 +SHL3 LDY IPY +; INX +; JMP NEXTOP + JMP DROP +;* +;* SHIFT TOS-1 RIGHT BY TOS +;* +SHR STY IPY + LDA ESTKL,X + CMP #$08 + BCC SHR2 + LDY ESTKH+1,X + STY ESTKL+1,X + CPY #$80 + LDY #$00 + BCC SHR1 + DEY +SHR1 STY ESTKH+1,X + SEC + SBC #$08 +SHR2 TAY + BEQ SHR4 + LDA ESTKH+1,X +SHR3 CMP #$80 + ROR + ROR ESTKL+1,X + DEY + BNE SHR3 + STA ESTKH+1,X +SHR4 LDY IPY +; INX +; JMP NEXTOP + JMP DROP +;* +;* LOGICAL NOT +;* +LNOT LDA ESTKL,X + ORA ESTKH,X + BEQ LNOT1 + LDA #$FF +LNOT1 EOR #$FF + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +;* +;* LOGICAL AND +;* +LAND LDA ESTKL+1,X + ORA ESTKH+1,X + BEQ LAND2 + LDA ESTKL,X + ORA ESTKH,X + BEQ LAND1 + LDA #$FF +LAND1 STA ESTKL+1,X + STA ESTKH+1,X +;LAND2 INX +; JMP NEXTOP +LAND2 JMP DROP +;* +;* LOGICAL OR +;* +LOR LDA ESTKL,X + ORA ESTKH,X + ORA ESTKL+1,X + ORA ESTKH+1,X + BEQ LOR1 + LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X +;LOR1 INX +; JMP NEXTOP +LOR1 JMP DROP +;* +;* DUPLICATE TOS +;* +DUP DEX + LDA ESTKL+1,X + STA ESTKL,X + LDA ESTKH+1,X + STA ESTKH,X + JMP NEXTOP +;* +;* PUSH FROM EVAL STACK TO CALL STACK +;* +PUSH LDA ESTKL,X + PHA + LDA ESTKH,X + PHA +; INX +; JMP NEXTOP + JMP DROP +;* +;* PULL FROM CALL STACK TO EVAL STACK +;* +PULL DEX + PLA + STA ESTKH,X + PLA + STA ESTKL,X + JMP NEXTOP +;* +;* CONSTANT +;* +ZERO DEX + LDA #$00 + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +CB DEX + +INC_IP + LDA (IP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP +;* +;* LOAD ADDRESS & LOAD CONSTANT WORD (SAME THING, WITH OR WITHOUT FIXUP) +;* +LA = * +CW DEX + +INC_IP + LDA (IP),Y + STA ESTKL,X + +INC_IP + LDA (IP),Y + STA ESTKH,X + JMP NEXTOP +;* +;* CONSTANT STRING +;* +CS DEX + +INC_IP + TYA ; NORMALIZE IP AND SAVE STRING ADDR ON ESTK + CLC + ADC IPL + STA IPL + STA ESTKL,X + LDA #$00 + TAY + ADC IPH + STA IPH + STA ESTKH,X + LDA (IP),Y + TAY + JMP NEXTOP +;* +;* LOAD VALUE FROM ADDRESS TAG +;* +LB LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + STA ESTKL,X + STY ESTKH,X + LDY IPY + JMP NEXTOP +LW LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* LOAD ADDRESS OF LOCAL FRAME OFFSET +;* +LLA +INC_IP + LDA (IP),Y + DEX + CLC + ADC IFPL + STA ESTKL,X + LDA #$00 + ADC IFPH + STA ESTKH,X + JMP NEXTOP +;* +;* LOAD VALUE FROM LOCAL FRAME OFFSET +;* +LLB +INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + LDY IPY + JMP NEXTOP +LLW +INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + INY + LDA (IFP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* LOAD VALUE FROM ABSOLUTE ADDRESS +;* +LAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + STY ESTKH,X + LDY IPY + JMP NEXTOP +LAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* STORE VALUE TO ADDRESS +;* +SB LDA ESTKL+1,X + STA TMPL + LDA ESTKH+1,X + STA TMPH + LDA ESTKL,X + STY IPY + LDY #$00 + STA (TMP),Y + LDY IPY + INX +; INX +; JMP NEXTOP + JMP DROP +SW LDA ESTKL+1,X + STA TMPL + LDA ESTKH+1,X + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + INX +; INX +; JMP NEXTOP + JMP DROP +;* +;* STORE VALUE TO LOCAL FRAME OFFSET +;* +SLB +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +SLW +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +;* +;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK +;* +DLB +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY + JMP NEXTOP +DLW +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY + JMP NEXTOP +;* +;* STORE VALUE TO ABSOLUTE ADDRESS +;* +SAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + LDA ESTKL,X + STY IPY + LDY #$00 + STA (TMP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +SAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +;* +;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK +;* +DAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + LDY IPY + JMP NEXTOP +DAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + JMP NEXTOP +;* +;* COMPARES +;* +ISEQ LDA ESTKL,X + CMP ESTKL+1,X + BNE ISFLS + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISFLS +ISTRU LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +; +ISNE LDA ESTKL,X + CMP ESTKL+1,X + BNE ISTRU + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISTRU +ISFLS LDA #$00 + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP +; +ISGE LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVC ISGE1 + EOR #$80 +ISGE1 BPL ISTRU + BMI ISFLS +; +ISGT LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVC ISGT1 + EOR #$80 +ISGT1 BMI ISTRU + BPL ISFLS +; +ISLE LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVC ISLE1 + EOR #$80 +ISLE1 BPL ISTRU + BMI ISFLS +; +ISLT LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVC ISLT1 + EOR #$80 +ISLT1 BMI ISTRU + BPL ISFLS +;* +;* BRANCHES +;* +BRTRU INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE BRNCH +NOBRNCH +INC_IP + +INC_IP + JMP NEXTOP +BRFLS INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE NOBRNCH +BRNCH LDA IPH + STA TMPH + LDA IPL + +INC_IP + CLC + ADC (IP),Y + STA TMPL + LDA TMPH + +INC_IP + ADC (IP),Y + STA IPH + LDA TMPL + STA IPL + DEY + DEY + JMP NEXTOP +BREQ INX + LDA ESTKL-1,X + CMP ESTKL,X + BNE NOBRNCH + LDA ESTKH-1,X + CMP ESTKH,X + BEQ BRNCH + BNE NOBRNCH +BRNE INX + LDA ESTKL-1,X + CMP ESTKL,X + BNE BRNCH + LDA ESTKH-1,X + CMP ESTKH,X + BEQ NOBRNCH + BNE BRNCH +BRGT INX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BMI BRNCH + BPL NOBRNCH +BRLT INX + LDA ESTKL,X + CMP ESTKL-1,X + LDA ESTKH,X + SBC ESTKH-1,X + BMI BRNCH + BPL NOBRNCH +IBRNCH LDA IPL + CLC + ADC ESTKL,X + STA IPL + LDA IPH + ADC ESTKH,X + STA IPH +; INX +; JMP NEXTOP + JMP DROP +;* +;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) +;* +CALL +INC_IP + LDA (IP),Y + STA CALLADR+1 + +INC_IP + LDA (IP),Y + STA CALLADR+2 + LDA IPH + PHA + LDA IPL + PHA + TYA + PHA +CALLADR JSR $FFFF + PLA + TAY + PLA + STA IPL + PLA + STA IPH + JMP NEXTOP +;* +;* INDIRECT CALL TO ADDRESS (NATIVE CODE) +;* +ICAL LDA ESTKL,X + STA ICALADR+1 + LDA ESTKH,X + STA ICALADR+2 + INX + LDA IPH + PHA + LDA IPL + PHA + TYA + PHA +ICALADR JSR $FFFF + PLA + TAY + PLA + STA IPL + PLA + STA IPH + JMP NEXTOP +;* +;* ENTER FUNCTION WITH FRAME SIZE AND PARAM COUNT +;* +ENTER INY + LDA (IP),Y + PHA ; SAVE ON STACK FOR LEAVE + EOR #$FF + SEC + ADC IFPL + STA IFPL + BCS + + DEC IFPH ++ INY + LDA (IP),Y + ASL + TAY + BEQ + +- LDA ESTKH,X + DEY + STA (IFP),Y + LDA ESTKL,X + INX + DEY + STA (IFP),Y + BNE - ++ LDY #$02 + JMP NEXTOP +;* +;* LEAVE FUNCTION +;* +LEAVE PLA + CLC + ADC IFPL + STA IFPL + BCS LIFPH + RTS +LIFPH INC IFPH +RET RTS +;* +;* OPCODE TABLE +;* + !ALIGN 255,0 +OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E + !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E + !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E + !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E + !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E + !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E + !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E +;* +;*SAVED ZERO PAGE +;* +ZPSAVE !FILL 256 +;* +;* SOURCE PWM ASM/PLASMA PROGRAM +;* + !SOURCE "a2pwm.s" +START !SOURCE "hilopwm.a" +SEGEND = * +VMINIT LDY #$10 ; INSTALL PAGE 0 FETCHOP ROUTINE +- LDA PAGE0-1,Y + STA DROP-1,Y + DEY + BNE - + JMP START +PAGE0 = * + !PSEUDOPC $00EF { +;* +;* INTERP BYTECODE INNER LOOP +;* + INX ; DROP + INY ; NEXTOP + BEQ NEXTOPH + LDA $FFFF,Y ; FETCHOP @ $F3, IP MAPS OVER $FFFF @ $F4 + STA OPIDX + JMP (OPTBL) +NEXTOPH INC IPH + BNE FETCHOP +} diff --git a/src/samplesrc/a2pwm/util.pla b/src/samplesrc/a2pwm/util.pla new file mode 100644 index 0000000..4ad9d8a --- /dev/null +++ b/src/samplesrc/a2pwm/util.pla @@ -0,0 +1,404 @@ +// +// Colors +// +const BLACK = 0 +const MAGENTA = 1 +const DRKBLU = 2 +const PURPLE = 3 +const DRKGRN = 4 +const GREY = 5 +const MEDBLU = 6 +const LGTBLU = 7 +const BROWN = 8 +const ORANGE = 9 +const GRAY = 10 +const PINK = 11 +const LGTGRN = 12 +const YELLOW = 13 +const AQUA = 14 +const WHITE = 15 + +word txt1scrn[] = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 +word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 +word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 +// +// CALL 6502 ROUTINE +// CALL(ADDR, AREG, XREG, YREG, STATUS) +// +asm call + PHP + LDA ESTKL+4,X + STA CALL6502+1 + LDA ESTKH+4,X + STA CALL6502+2 + LDA ESTKL,X + PHA + LDA ESTKL+1,X + TAY + LDA ESTKL+3,X + PHA + LDA ESTKL+2,X + INX + INX + INX + INX + STX ESP + TAX + PLA + PLP +CALL6502 JSR $FFFF + PHP + STA REGVALS+0 + STX REGVALS+1 + STY REGVALS+2 + PLA + STA REGVALS+3 + LDX ESP + LDA #REGVALS + STA ESTKL,X + STY ESTKH,X + PLP + RTS +REGVALS !FILL 4 +end +// +// SET MEMORY TO VALUE +// MEMSET(ADDR, VALUE, SIZE) +// With optimizations from Peter Ferrie +// +asm memset + LDA ESTKL+2,X + STA DSTL + LDA ESTKH+2,X + STA DSTH + LDY ESTKL,X + BEQ + + INC ESTKH,X + LDY #$00 ++ LDA ESTKH,X + BEQ SETMEX +SETMLPL CLC + LDA ESTKL+1,X +SETMLPH STA (DST),Y + DEC ESTKL,X + BEQ ++ +- INY + BEQ + +-- BCS SETMLPL + SEC + LDA ESTKH+1,X + BCS SETMLPH ++ INC DSTH + BNE -- +++ DEC ESTKH,X + BNE - +SETMEX INX + INX + RTS +end +// +// COPY MEMORY +// MEMCPY(DSTADDR, SRCADDR, SIZE) +// +asm memcpy + INX + INX + LDA ESTKL-2,X + ORA ESTKH-2,X + BEQ CPYMEX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BCC REVCPY +; +; FORWARD COPY +; + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL-1,X + STA SRCL + LDA ESTKH-1,X + STA SRCH + LDY ESTKL-2,X + BEQ FORCPYLP + INC ESTKH-2,X + LDY #$00 +FORCPYLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL-2,X + BNE FORCPYLP + DEC ESTKH-2,X + BNE FORCPYLP + RTS +; +; REVERSE COPY +; +REVCPY ;CLC + LDA ESTKL-2,X + ADC ESTKL,X + STA DSTL + LDA ESTKH-2,X + ADC ESTKH,X + STA DSTH + CLC + LDA ESTKL-2,X + ADC ESTKL-1,X + STA SRCL + LDA ESTKH-2,X + ADC ESTKH-1,X + STA SRCH + DEC DSTH + DEC SRCH + LDY #$FF + LDA ESTKL-2,X + BEQ REVCPYLP + INC ESTKH-2,X +REVCPYLP LDA (SRC),Y + STA (DST),Y + DEY + CPY #$FF + BNE + + DEC DSTH + DEC SRCH ++ DEC ESTKL-2,X + BNE REVCPYLP + DEC ESTKH-2,X + BNE REVCPYLP +CPYMEX RTS +end +// +// Unsigned word comparisons. +// +asm uword_isge + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm uword_isle + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm uword_isgt + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm uword_islt + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +// +// Addresses of internal routines. +// +asm _hilopwm + TXA + PHA + JSR HILOPWM + PLA + TAX + DEX + RTS +end +asm toupper + LDA ESTKL,X +TOUPR AND #$7F + CMP #'a' + BCC + + CMP #'z'+1 + BCS + + SBC #$1F ++ STA ESTKL,X + RTS +end +// +// CONSOLE I/O +// +asm putc + LDA ESTKL,X +; JSR TOUPR + ORA #$80 + JMP $FDF0 +end +asm getc + DEX +- LDA $C000 + BPL - + BIT $C010 + AND #$7F + STA ESTKL,X + LDA #$00 + STA ESTKH,X + RTS +end +def keypressed + return ^$C000 >= 128 +end +def pdl(num) + return call($FB1E, 0, num, 0, 0)->2 +end +def bttn(num) + return (^$C061+num) >= 128 +end +def putln + return putc($0D) +end +def puts(str) + byte i + + for i = 1 to ^str + putc(^(str+i)) + next +end +def puti(i) + byte numstr[7] + byte place, sign + + place = 6 + if i < 0 + sign = 1 + i = -i + else + sign = 0 + fin + while i >= 10 + numstr[place] = i % 10 + '0' + i = i / 10 + place-- + loop + numstr[place] = i + '0' + place-- + if sign + numstr[place] = '-' + place-- + fin + numstr[place] = 6 - place + return puts(@numstr[place]) +end +def normal + ^$32 = $FF +end +def inverse + ^$32 = $3F +end +def gotoxy(x, y) + ^$24 = x + ^$20 + return call($FB5B, y + ^$22, 0, 0, 0) +end +def home + return call($FC58, 0, 0, 0, 0) +end +def putsxy(x, y, str) + gotoxy(x, y) + return puts(str) +end +def textmode + call($FB39, 0, 0, 0, 0) // textmode() + return home +end +// +// Clear viewport to white +// +def clearview + byte i + word c + inverse + c = ' ' | $80 & ^$32 + c = c | (c << 8) + for i = ^$22 to ^$23 + memset(txt1scrn[i] + ^$20, c, ^$21) + next + return gotoxy(0,0) +end +def grmode + call($FB2F, 0, 0, 0, 0) // initmode() + call($FB40, 0, 0, 0, 0) // grmode() + return home +end +def grcolor(color) + return call($F864, color, 0, 0, 0) +end +def plot(x, y) + return call($F800, y, 0, x, 0) +end +def hlin(left, right, y) + ^$2C = right; + return call($F819, y, 0, left, 0) +end +def vlin(top, bottom, x) + ^$2D = bottom; + return call($F828, top, 0, x, 0) +end +def rect(left, right, top, bottom, fill) + byte y + + hlin(left, right, top) + hlin(left, right, bottom) + top++ + bottom-- + if fill + for y = top to bottom + hlin(left, right, y) + next + else + vlin(top, bottom, left) + vlin(top, bottom, right) + fin +end +// +// HFO/LFO PWM sound routines +// +def envelope(attack, decay, sustain, release, ainc, dinc, rinc) + ^$0C = attack + ^$0D = decay + ^$0E = sustain + ^$0F = release + *$10 = ainc + *$12 = dinc + *$14 = rinc +end +def hilopwm(HFO, LFO, LFOusr) + ^$08 = HFO + ^$09 = LFO + *$0A = LFOusr + return _hilopwm +end From 62b47d0d0f168b7585949c39e5134006481f55e4 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Tue, 25 Apr 2017 11:57:11 -0700 Subject: [PATCH 19/58] Fix CALL6502 --- src/vmsrc/a1cmd.pla | 860 ++++++++++++++++++++++---------------------- 1 file changed, 430 insertions(+), 430 deletions(-) diff --git a/src/vmsrc/a1cmd.pla b/src/vmsrc/a1cmd.pla index 2fc191e..b2ce603 100644 --- a/src/vmsrc/a1cmd.pla +++ b/src/vmsrc/a1cmd.pla @@ -89,19 +89,19 @@ byte loadstr[] = "MODLOAD" byte execstr[] = "MODEXEC" byte modadrstr[] = "MODADDR" byte argstr[] = "ARGS" -word exports[] = @sysstr, @syscall -word = @callstr, @call -word = @putcstr, @cout +word exports[] = @sysstr, @syscall +word = @callstr, @call +word = @putcstr, @cout word = @putlnstr, @crout -word = @putsstr, @prstr -word = @getcstr, @cin -word = @getsstr, @rdstr -word = @hpmarkstr, @markheap -word = @hpallocstr,@allocheap -word = @hpalignstr,@allocalignheap -word = @hprelstr, @releaseheap -word = @memsetstr, @memset -word = @memcpystr, @memcpy +word = @putsstr, @prstr +word = @getcstr, @cin +word = @getsstr, @rdstr +word = @hpmarkstr, @markheap +word = @hpallocstr,@allocheap +word = @hpalignstr,@allocalignheap +word = @hprelstr, @releaseheap +word = @memsetstr, @memset +word = @memcpystr, @memcpy word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt @@ -118,42 +118,42 @@ word syslibsym = @exports // SYSCALL(CMD) // asm syscall - LDA ESTKL,X - STX ESP - TAX - JSR $900C - LDX ESP - LDY #$00 - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STX ESP + TAX + JSR $900C + LDX ESP + LDY #$00 + STA ESTKL,X + STY ESTKH,X + RTS end // // CALL 6502 ROUTINE -// CALL(AREG, XREG, YREG, STATUS, ADDR) +// CALL(ADDR, AREG, XREG, YREG, STATUS) // asm call -REGVALS = SRC PHP - LDA ESTKL,X - STA TMPL - LDA ESTKH,X - STA TMPH - INX + LDA ESTKL+4,X + STA CALL6502+1 + LDA ESTKH+4,X + STA CALL6502+2 LDA ESTKL,X PHA - INX - LDY ESTKL,X - INX LDA ESTKL+1,X + TAY + LDA ESTKL+3,X PHA - LDA ESTKL,X + LDA ESTKL+2,X + INX + INX + INX INX STX ESP TAX PLA PLP - JSR JMPTMP +CALL6502 JSR $FFFF PHP STA REGVALS+0 STX REGVALS+1 @@ -167,13 +167,13 @@ REGVALS = SRC STY ESTKH,X PLP RTS -JMPTMP JMP (TMP) +REGVALS !FILL 4 end // // QUIT TO MONITOR // asm quit - JMP $9000 + JMP $9000 end // // SET MEMORY TO VALUE @@ -181,175 +181,175 @@ end // With optimizations from Peter Ferrie // asm memset - LDA ESTKL+2,X - STA DSTL - LDA ESTKH+2,X - STA DSTH - LDY ESTKL,X - BEQ + - INC ESTKH,X - LDY #$00 -+ LDA ESTKH,X - BEQ SETMEX -SETMLPL CLC - LDA ESTKL+1,X -SETMLPH STA (DST),Y - DEC ESTKL,X - BEQ ++ -- INY - BEQ + --- BCS SETMLPL - SEC - LDA ESTKH+1,X - BCS SETMLPH -+ INC DSTH - BNE -- -++ DEC ESTKH,X - BNE - -SETMEX INX - INX - RTS + LDA ESTKL+2,X + STA DSTL + LDA ESTKH+2,X + STA DSTH + LDY ESTKL,X + BEQ + + INC ESTKH,X + LDY #$00 ++ LDA ESTKH,X + BEQ SETMEX +SETMLPL CLC + LDA ESTKL+1,X +SETMLPH STA (DST),Y + DEC ESTKL,X + BEQ ++ +- INY + BEQ + +-- BCS SETMLPL + SEC + LDA ESTKH+1,X + BCS SETMLPH ++ INC DSTH + BNE -- +++ DEC ESTKH,X + BNE - +SETMEX INX + INX + RTS end // // COPY MEMORY // MEMCPY(DSTADDR, SRCADDR, SIZE) // asm memcpy - INX - INX - LDA ESTKL-2,X - ORA ESTKH-2,X - BEQ CPYMEX - LDA ESTKL-1,X - CMP ESTKL,X - LDA ESTKH-1,X - SBC ESTKH,X - BCC REVCPY + INX + INX + LDA ESTKL-2,X + ORA ESTKH-2,X + BEQ CPYMEX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BCC REVCPY ; ; FORWARD COPY ; - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL-1,X - STA SRCL - LDA ESTKH-1,X - STA SRCH - LDY ESTKL-2,X - BEQ FORCPYLP - INC ESTKH-2,X - LDY #$00 -FORCPYLP LDA (SRC),Y - STA (DST),Y - INY - BNE + - INC DSTH - INC SRCH -+ DEC ESTKL-2,X - BNE FORCPYLP - DEC ESTKH-2,X - BNE FORCPYLP - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL-1,X + STA SRCL + LDA ESTKH-1,X + STA SRCH + LDY ESTKL-2,X + BEQ FORCPYLP + INC ESTKH-2,X + LDY #$00 +FORCPYLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL-2,X + BNE FORCPYLP + DEC ESTKH-2,X + BNE FORCPYLP + RTS ; ; REVERSE COPY ; -REVCPY ;CLC - LDA ESTKL-2,X - ADC ESTKL,X - STA DSTL - LDA ESTKH-2,X - ADC ESTKH,X - STA DSTH - CLC - LDA ESTKL-2,X - ADC ESTKL-1,X - STA SRCL - LDA ESTKH-2,X - ADC ESTKH-1,X - STA SRCH - DEC DSTH - DEC SRCH - LDY #$FF - LDA ESTKL-2,X - BEQ REVCPYLP - INC ESTKH-2,X -REVCPYLP LDA (SRC),Y - STA (DST),Y - DEY - CPY #$FF - BNE + - DEC DSTH - DEC SRCH -+ DEC ESTKL-2,X - BNE REVCPYLP - DEC ESTKH-2,X - BNE REVCPYLP -CPYMEX RTS +REVCPY ;CLC + LDA ESTKL-2,X + ADC ESTKL,X + STA DSTL + LDA ESTKH-2,X + ADC ESTKH,X + STA DSTH + CLC + LDA ESTKL-2,X + ADC ESTKL-1,X + STA SRCL + LDA ESTKH-2,X + ADC ESTKH-1,X + STA SRCH + DEC DSTH + DEC SRCH + LDY #$FF + LDA ESTKL-2,X + BEQ REVCPYLP + INC ESTKH-2,X +REVCPYLP LDA (SRC),Y + STA (DST),Y + DEY + CPY #$FF + BNE + + DEC DSTH + DEC SRCH ++ DEC ESTKL-2,X + BNE REVCPYLP + DEC ESTKH-2,X + BNE REVCPYLP +CPYMEX RTS end // // Unsigned word comparisons. // asm uword_isge - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isle - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isgt - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_islt - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end // // Addresses of internal routines. // asm interp - DEX - LDA #IINTERP - STA ESTKH,X - RTS + DEX + LDA #IINTERP + STA ESTKH,X + RTS end // // A DCI string is one that has the high bit set for every character except the last. @@ -367,28 +367,28 @@ end // return len //end asm dcitos - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDY #$00 -- LDA (SRC),Y - CMP #$80 - AND #$7F - INY - STA (DST),Y - BCS - - TYA - LDY #$00 - STA (DST),Y - INX - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDY #$00 +- LDA (SRC),Y + CMP #$80 + AND #$7F + INY + STA (DST),Y + BCS - + TYA + LDY #$00 + STA (DST),Y + INX + STA ESTKL,X + STY ESTKH,X + RTS end //def stodci(str, dci) // byte len, c @@ -400,50 +400,50 @@ end // len = len - 1 // (dci).[len] = c // while len -// c = toupper((str).[len]) | $80 -// len = len - 1 -// (dci).[len] = c +// c = toupper((str).[len]) | $80 +// len = len - 1 +// (dci).[len] = c // loop // return ^str //end asm stodci - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - INX - LDY #$00 - LDA (SRC),Y - BEQ ++ - TAY - LDA (SRC),Y - JSR TOUPR - BNE + -- LDA (SRC),Y - JSR TOUPR - ORA #$80 -+ DEY - STA (DST),Y - BNE - - LDA (SRC),Y -++ STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + INX + LDY #$00 + LDA (SRC),Y + BEQ ++ + TAY + LDA (SRC),Y + JSR TOUPR + BNE + +- LDA (SRC),Y + JSR TOUPR + ORA #$80 ++ DEY + STA (DST),Y + BNE - + LDA (SRC),Y +++ STA ESTKL,X + STY ESTKH,X + RTS end asm toupper - LDA ESTKL,X -TOUPR AND #$7F - CMP #'a' - BCC + - CMP #'z'+1 - BCS + - SBC #$1F -+ STA ESTKL,X - RTS + LDA ESTKL,X +TOUPR AND #$7F + CMP #'a' + BCC + + CMP #'z'+1 + BCS + + SBC #$1F ++ STA ESTKL,X + RTS end // // Module symbols are entered into the symbol table @@ -462,25 +462,25 @@ end // return dci //end asm modtosym - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDA ESTKL,X - STA ESTKL+1,X - STA DSTL - LDA ESTKH,X - STA ESTKH+1,X - STA DSTH - INX - LDY #$00 - LDA #'#'+$80 -- STA (DST),Y - ASL - LDA (SRC),Y - INY - BCS - - RTS + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDA ESTKL,X + STA ESTKL+1,X + STA DSTL + LDA ESTKH,X + STA ESTKH+1,X + STA DSTH + INX + LDY #$00 + LDA #'#'+$80 +- STA (DST),Y + ASL + LDA (SRC),Y + INY + BCS - + RTS end // // Lookup routines. @@ -503,66 +503,66 @@ end // loop // return 0 asm lookuptbl - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDY #$00 -- LDA (DST),Y - BEQ + - CMP (SRC),Y - BNE ++ - INY - ASL - BCS - - LDA (DST),Y - PHA - INY - LDA (DST),Y - TAY - PLA -+ INX - STA ESTKL,X - STY ESTKH,X - RTS -++ LDY #$00 --- LDA (DST),Y - INC DSTL - BEQ + ---- ASL - BCS -- - LDA #$02 - ADC DSTL - STA DSTL - BCC - - INC DSTH - BCS - -+ INC DSTH - BNE --- + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDY #$00 +- LDA (DST),Y + BEQ + + CMP (SRC),Y + BNE ++ + INY + ASL + BCS - + LDA (DST),Y + PHA + INY + LDA (DST),Y + TAY + PLA ++ INX + STA ESTKL,X + STY ESTKH,X + RTS +++ LDY #$00 +-- LDA (DST),Y + INC DSTL + BEQ + +--- ASL + BCS -- + LDA #$02 + ADC DSTL + STA DSTL + BCC - + INC DSTH + BCS - ++ INC DSTH + BNE --- end // // CONSOLE I/O // asm cout - LDA ESTKL,X - JSR TOUPR - ORA #$80 - JMP $FFEF + LDA ESTKL,X + JSR TOUPR + ORA #$80 + JMP $FFEF end asm cin - DEX -- LDA $D011 - BPL - - LDA $D010 - AND #$7F - STA ESTKL,X - LDA #$00 - STA ESTKH,X - RTS + DEX +- LDA $D011 + BPL - + LDA $D010 + AND #$7F + STA ESTKL,X + LDA #$00 + STA ESTKH,X + RTS end def crout return cout($0D) @@ -572,7 +572,7 @@ def prstr(str) i = 1 while i <= ^str cout((str)[i]) - i = i + 1 + i = i + 1 loop end def rdstr(prompt) @@ -582,47 +582,47 @@ def rdstr(prompt) cout(prompt) repeat ch = cin - when ch - is $15 // right arrow - if inbuff.0 < maxlen - inbuff.0 = inbuff.0 + 1 - ch = inbuff[inbuff.0] - cout(ch) - fin - is $08 // left arrow - if inbuff.0 - cout('\\') - cout(inbuff[inbuff.0]) - inbuff.0 = inbuff.0 - 1 - fin - is $04 // ctrl-d - if inbuff.0 - cout('#') - cout(inbuff[inbuff.0]) - memcpy(inbuff + inbuff.0, inbuff + inbuff.0 + 1, maxlen - inbuff.0) - maxlen = maxlen - 1 - inbuff.0 = inbuff.0 - 1 - fin - is $0C // ctrl-l - crout - prstr(inbuff) - is $0D // return - is $18 // ctrl-x - crout - inbuff.0 = 0 - is $9B // escape - inbuff.0 = 0 - ch = $0D - otherwise - if ch >= ' ' - cout(ch) - inbuff.0 = inbuff.0 + 1 - inbuff[inbuff.0] = ch - if inbuff.0 > maxlen - maxlen = inbuff.0 - fin - fin - wend + when ch + is $15 // right arrow + if inbuff.0 < maxlen + inbuff.0 = inbuff.0 + 1 + ch = inbuff[inbuff.0] + cout(ch) + fin + is $08 // left arrow + if inbuff.0 + cout('\\') + cout(inbuff[inbuff.0]) + inbuff.0 = inbuff.0 - 1 + fin + is $04 // ctrl-d + if inbuff.0 + cout('#') + cout(inbuff[inbuff.0]) + memcpy(inbuff + inbuff.0, inbuff + inbuff.0 + 1, maxlen - inbuff.0) + maxlen = maxlen - 1 + inbuff.0 = inbuff.0 - 1 + fin + is $0C // ctrl-l + crout + prstr(inbuff) + is $0D // return + is $18 // ctrl-x + crout + inbuff.0 = 0 + is $9B // escape + inbuff.0 = 0 + ch = $0D + otherwise + if ch >= ' ' + cout(ch) + inbuff.0 = inbuff.0 + 1 + inbuff[inbuff.0] = ch + if inbuff.0 > maxlen + maxlen = inbuff.0 + fin + fin + wend until ch == $0D or inbuff.0 == $7F cout($0D) return inbuff @@ -735,12 +735,12 @@ def lookupextern(esd, index) esd = esd + dcitos(esd, @str) if esd->0 & $10 and esd->1 == index addr = lookupsym(sym) - if !addr + if !addr perr = $81 - cout('?') - prstr(@str) - crout - fin + cout('?') + prstr(@str) + crout + fin return addr fin esd = esd + 3 @@ -783,10 +783,10 @@ def loadmod(mod) fin if rdlen > 0 readfile(@filename, heap) - memcpy(@header, heap, 128) - modsize = header:0 - moddep = @header.1 - defofst = modsize + memcpy(@header, heap, 128) + modsize = header:0 + moddep = @header.1 + defofst = modsize init = 0 if rdlen > 4 and heap=>2 == $DA7E // DAVE = magic number :-) // @@ -796,44 +796,44 @@ def loadmod(mod) defcnt = header:8 init = header:10 moddep = @header.12 - // - // Load module dependencies. - // + // + // Load module dependencies. + // while ^moddep if !lookupmod(moddep) if loadmod(moddep) < 0 - return -perr - fin + return -perr + fin fin moddep = moddep + dcitos(moddep, @str) loop - // - // Init def table. - // - deftbl = allocheap(defcnt * 5 + 1) - deflast = deftbl - ^deflast = 0 - // - // Re-read file - // - readfile(@filename, heap) + // + // Init def table. + // + deftbl = allocheap(defcnt * 5 + 1) + deflast = deftbl + ^deflast = 0 + // + // Re-read file + // + readfile(@filename, heap) fin - // - // Alloc heap space for relocated module (data + bytecode). - // - moddep = moddep + 1 - @header + heap - modfix = moddep - (heap + 2) // Adjust to skip header - modsize = modsize - modfix - rdlen = rdlen - modfix - 2 - modaddr = allocheap(modsize) - memcpy(modaddr, moddep, rdlen) - // - // Add module to symbol table. - // - addmod(mod, modaddr) - // - // Apply all fixups and symbol import/export. - // + // + // Alloc heap space for relocated module (data + bytecode). + // + moddep = moddep + 1 - @header + heap + modfix = moddep - (heap + 2) // Adjust to skip header + modsize = modsize - modfix + rdlen = rdlen - modfix - 2 + modaddr = allocheap(modsize) + memcpy(modaddr, moddep, rdlen) + // + // Add module to symbol table. + // + addmod(mod, modaddr) + // + // Apply all fixups and symbol import/export. + // modfix = modaddr - modfix bytecode = defofst + modfix - MODADDR modend = modaddr + modsize @@ -841,28 +841,28 @@ def loadmod(mod) esd = rld // Extern+Entry Symbol Directory while ^esd // Scan to end of ESD esd = esd + 4 - loop + loop esd = esd + 1 // // Run through the Re-Location Dictionary. // while ^rld if ^rld == $02 - // - // This is a bytcode def entry - add it to the def directory. - // + // + // This is a bytcode def entry - add it to the def directory. + // adddef(rld=>1 - defofst + bytecode, @deflast) else addr = rld=>1 + modfix if uword_isge(addr, modaddr) // Skip fixups to header if ^rld & $80 // WORD sized fixup. fixup = *addr - else // BYTE sized fixup. + else // BYTE sized fixup. fixup = ^addr fin if ^rld & $10 // EXTERN reference. fixup = fixup + lookupextern(esd, rld->3) - else // INTERN fixup. + else // INTERN fixup. fixup = fixup + modfix - MODADDR if uword_isge(fixup, bytecode) // @@ -873,28 +873,28 @@ def loadmod(mod) fin if ^rld & $80 // WORD sized fixup. *addr = fixup - else // BYTE sized fixup. + else // BYTE sized fixup. ^addr = fixup fin fin fin rld = rld + 4 loop - // + // // Run through the External/Entry Symbol Directory. - // + // while ^esd sym = esd esd = esd + dcitos(esd, @str) if ^esd & $08 - // + // // EXPORT symbol - add it to the global symbol table. - // + // addr = esd=>1 + modfix - MODADDR if uword_isge(addr, bytecode) - // - // Use the def directory address for bytecode. - // + // + // Use the def directory address for bytecode. + // addr = lookupdef(addr - bytecode + bytecode, deftbl) fin addsym(sym, addr) @@ -910,13 +910,13 @@ def loadmod(mod) // fixup = 0 if init - fixup = adddef(init - defofst + bytecode, @deflast)() + fixup = adddef(init - defofst + bytecode, @deflast)() if fixup < 0 perr = -fixup fin - if !(systemflags & modinitkeep) + if !(systemflags & modinitkeep) modend = init - defofst + bytecode - fin + fin fin // // Free up the end-of-module in main memory. @@ -948,9 +948,9 @@ def striptrail(strptr) for i = 1 to ^strptr if (strptr)[i] == ' ' - ^strptr = i - 1 - return - fin + ^strptr = i - 1 + return + fin next end def parsecmd(strptr) @@ -973,14 +973,14 @@ def execmod(modfile) perr = 1 if stodci(modfile, @moddci) saveheap = heap - savesym = lastsym - saveflags = systemflags - if loadmod(@moddci) < modkeep - lastsym = savesym - heap = saveheap - fin - ^lastsym = 0 - systemflags = saveflags + savesym = lastsym + saveflags = systemflags + if loadmod(@moddci) < modkeep + lastsym = savesym + heap = saveheap + fin + ^lastsym = 0 + systemflags = saveflags fin return -perr end @@ -1031,24 +1031,24 @@ while 1 if ^cmdptr when toupper(parsecmd(cmdptr)) is 'Q' - quit - is 'M' - syscall($02) - break - is '+' - execmod(cmdptr) - break - otherwise - prstr(@huhstr) + quit + is 'M' + syscall($02) + break + is '+' + execmod(cmdptr) + break + otherwise + prstr(@huhstr) wend if perr prstr(@errorstr) - prbyte(perr) - perr = 0 + prbyte(perr) + perr = 0 else prstr(@okstr) fin - crout() + crout() fin prstr(@prompt) cmdptr = rdstr($BA) From 3f7ce730033f645f2f49231a3949a150c8edae6d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 25 Apr 2017 13:22:36 -0700 Subject: [PATCH 20/58] Remove unused routine --- src/samplesrc/a2pwm/hilopwm.pla | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 3b43142..7d91150 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -41,18 +41,6 @@ word relRate = $00FF // include "util.pla" // -// Clear viewport to white -// -def clearWin - byte i, j - inverse - home - for j = 0 to 3 - for i = 0 to 39; putc(' '); next - next - return gotoxy(0,0) -end -// // Display LFO bar // def showLFO From 9c7f987cdfb2473e08e9868e88d36450079814d7 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Tue, 25 Apr 2017 22:30:03 -0700 Subject: [PATCH 21/58] Macro capability --- SANDBOX.PO | Bin 143360 -> 143360 bytes src/samplesrc/a2pwm/._demo.po | Bin 0 -> 4096 bytes src/samplesrc/a2pwm/._lfo.po | Bin 0 -> 4096 bytes src/samplesrc/a2pwm/hilopwm.pla | 498 +++++++++++++++++++++++++------- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes src/samplesrc/a2pwm/makefile | 2 +- src/samplesrc/a2pwm/util.pla | 411 ++++++++++++++++---------- 7 files changed, 654 insertions(+), 257 deletions(-) create mode 100755 src/samplesrc/a2pwm/._demo.po create mode 100755 src/samplesrc/a2pwm/._lfo.po diff --git a/SANDBOX.PO b/SANDBOX.PO index e81dcd9799d7096ad9f8b6e014a7519c460457cd..25b2a17fc461d0d8c0073b4a4591f6e2b79c494f 100755 GIT binary patch delta 568 zcmY+BKTpC?6vgj-5Gj8J0*yha1Og6{MpQt@LNOsx+CWKI{Q}0t#0_+HB-l?N6N8Zu zH+SRW0-FhmgNsoYSMj|^A=shm``vTTIq7Rpg!V+Z6YYK@QE&l&lJK_ajSSNEYg=ml zuu@gaHMyo~1{*$o0fG~Nsm~tY*+W=EMes%f3UpdsDjXiwH#G>rK_Oef-8 Y$8NK8xzQTLg$p!Ko-yrpNB{r; delta 133 zcmZp8z|ru4V}lrrzyw({K?X2TW_Ya5E3sLPrJGrm!Ohdp#WhIJ#WBPYBzcmbk&$5o zBLhfv!M^7V3^sBa+>@`d>uqML`@^`2OO}a^k%58vu-s-vfxC=Ne9QP4FR$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIgo;|%-Cq47!KeV z5)#CmaDEX)2g3}YGG;WTj6gnATqHR^SFbFysH8M8Co@y8EI%hNA84(q37VEs?q~>% zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2;dI^P-hc_!9Xq~BePhcD784hv?w`M zAuYcsTOl*ABsH%jGe0jeC#O;&CpE1^At@&@FB{m?h3Xp86srH>UXfvt`~M#R-1aD8 literal 0 HcmV?d00001 diff --git a/src/samplesrc/a2pwm/._lfo.po b/src/samplesrc/a2pwm/._lfo.po new file mode 100755 index 0000000000000000000000000000000000000000..d5a959f9b4ffeab05290e7a33c76704157a98fbf GIT binary patch literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIgo;|%-Cq47!KeV z5)#CmaDF932g3}YGG;WTj6gnATqHR^SFbFysH8M8Co@y8EI%hNA84(q37VEs?q~>% zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2;dI^P-hc_!9Xq~BePhcD784hv?w`M zAuYcsTOl*ABsH%jGe0jeC#O;&CpE1^At@&@FB{m?h3Xp86srH>UXfvt`~M#RN{A?E literal 0 HcmV?d00001 diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 7d91150..c4e937c 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -1,8 +1,30 @@ const inbuff = $200 const freemem = $0002 +const iobuffer = 0x1800 +const NMACROS = 7 const FALSE = 0 const TRUE = !FALSE // +// Macro sequence structure +// +struc t_macro + byte absStart + byte durAtk + byte durDcy + byte durSus + byte durRel + word rateAtk + word rateDcy + word rateRel + byte idxOctave + byte perLFO + byte idxLFO + byte[256] sequence +end +word macros // Pointer to macros +byte record[t_macro] // Recording buffer +word recording = FALSE // Recording key/flag +// // System variables. // word heap @@ -15,6 +37,14 @@ byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 99, 93, 88, 83, 78 // byte keytone[] = 'A','S','E','D','R','F','G','Y','H','U','J','I','K','L' // +// Macro sequence keys +// +byte keymacro[] = 'Z', 'X', 'C', 'V', 'B', 'N', 'M' +// +// Macro record keys +// +byte keyrecord[] = $1A, $18, $03, $16, $02, $0E, $0D +// // Which octave are we in // byte octave = 1 @@ -37,10 +67,53 @@ word atkRate = $07FF word dcyRate = $0000 word relRate = $00FF // +// Patch filename +// +byte patch = "PATCH" +byte modPatch = FALSE +// // Import utility routines // include "util.pla" // +// Load/Save PATCH +// +def loadPatch + byte refnum + + refnum = open(@patch, iobuffer) + if refnum + read(refnum, macros, t_macro * NMACROS) // Macros + read(refnum, @octave, @patch - @octave) // Initial values + close(refnum) + fin +end +def savePatch + byte refnum + + destroy(@patch) + create(@patch, $C3, $06, $00) // full access, BIN file + refnum = open(@patch, iobuffer) + if refnum + write(refnum, macros, t_macro * NMACROS) // Macros + write(refnum, @octave, @patch - @octave) // Initial values + close(refnum) + modPatch = FALSE + fin +end +// +// Query routines +// +def query(str) + byte c + + inverse + clearview + putsxy(20 - ^str / 2, 2, str) + c = toupper(getc) + return c == 'Y' +end +// // Display LFO bar // def showLFO @@ -48,18 +121,21 @@ def showLFO LFObar = (LFO+7)/8 grcolor(WHITE) - rect(34, 39, 6, 39, FALSE) + rect(33, 39, 6, 39, FALSE) if LFObar < 32 grcolor(ORANGE) - rect(35, 38, 7, 38-LFObar, TRUE) + rect(34, 38, 7, 38-LFObar, TRUE) fin if LFObar grcolor(DRKBLU) - rect(35, 38, 39-LFObar, 38, TRUE) + rect(34, 38, 39-LFObar, 38, TRUE) fin - putsxy(36, 0, " ") - gotoxy(36, 0) - puti(LFO) + // + //Show actual value + // + putsxy(35, 0, " ") + gotoxy(35, 0) + return puti(LFO) end // // Display LFO waveform @@ -87,7 +163,7 @@ def showWaveform // // Restore envelope // - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + return envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) end // // Display duration @@ -111,6 +187,12 @@ def showDuration fin grcolor(AQUA) rect(left, right, 0, 5, TRUE) + // + // Show actual value + // + putsxy(5, 3, " ") + gotoxy(5, 3) + return puti(duration) end // // Display octave @@ -120,7 +202,35 @@ def showOctave putsxy(0, 1, "----------------------------------------") normal putsxy(octave*10, 1, "----------") + return inverse +end +def showMainPanel inverse + clearview + showDuration + showWaveform + showLFO + putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.0") + normal + putsxy(1, 0, "1-8") + gotoxy(34, 0); putc('<') + gotoxy(38, 0); putc('>') + gotoxy(3, 3); putc('-') + gotoxy(8, 3); putc('+') + inverse + showOctave + normal + putsxy(0, 2, "<-") + putsxy(38, 2, "->") + inverse + putsxy(11, 3, "A S D F G H J K L") + normal + gotoxy(14, 2); putc('E') + gotoxy(16, 2); putc('R') + gotoxy(20, 2); putc('Y') + gotoxy(22, 2); putc('U') + gotoxy(24, 2); putc('I') + return inverse end // // Recalc envelope parameters @@ -133,123 +243,315 @@ def recalcEnv relRate = $0FFF/relLen end // +// Rest +// +def restnote + byte d + + for d = duration downto 1 + call($FCA8, $6A, 0, 0, 0) + next +end +// +// playback a sequence +// +def playback(seq) + word macro + byte seq, key, i, showUpdate + + macro = macros + t_macro * seq + // + // Start off with initial conditions + // + showUpdate = 0 + if macro->absStart + if macro->idxOctave <> octave + octave = macro->idxOctave + showUpdate = showUpdate | 1 + fin + if macro->idxLFO <> LFOmap + LFOmap = macro->idxLFO + showUpdate = showUpdate | 2 + fin + if macro->perLFO <> LFO + LFO = macro->perLFO + showUpdate = showUpdate | 4 + fin + if macro->durAtk + macro->durDcy + macro->durSus + macro->durRel <> duration + envelope(macro->durAtk, macro->durDcy, macro->durSus, macro->durRel, macro=>rateAtk, macro=>rateDcy, macro=>rateRel) + duration = macro->durAtk + macro->durDcy + macro->durSus + macro->durRel + showUpdate = showUpdate | 8 + fin + fin + // + // Run throught the sequence + // + for seq = 1 to macro->sequence + key = macro->sequence[seq] + // + // Check for tone keys + // + for i = 0 to 13 + if keytone[i] == key + if LFO == 0 + hilopwm(scale[i]>>octave, LFO, 0) + else + hilopwm(scale[i]>>octave, LFO, LFOmap) + fin + break + fin + next + // + // Check for macro keys + // + if i > 13 + for i = 0 to 6 + if keymacro[i] == key + playback(i) + break + fin + next + if i > 6 + when key + is ' ' + restnote + break + is $15 // -> + octave++ + showUpdate = showUpdate | 1 + break + is $08 // <- + showUpdate = showUpdate | 1 + octave-- + break + is '1' + is '2' + is '3' + is '4' + is '5' + is '6' + is '7' + is '8' + LFOmap = key - '1' + showUpdate = showUpdate | 2 + break + is '<' + is ',' + LFO-- + showUpdate = showUpdate | 4 + break + is '>' + is '.' + LFO++ + showUpdate = showUpdate | 4 + break + is '+' + is $0B // UP + duration++ + recalcEnv + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + showUpdate = showUpdate | 8 + break + is '-' + is $0A // DOWN + duration-- + recalcEnv + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + showUpdate = showUpdate | 8 + break + wend + fin + fin + next + // + // Udate display + // + if showUpdate & 1; showOctave; fin + if showUpdate & 2; showWaveform; fin + if showUpdate & 4; showLFO; fin + if showUpdate & 8; showDuration; fin +end +// // Main loop // def main byte quit, key, i - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) quit = FALSE repeat if keypressed key = toupper(getc) - when key - is $1B // ESC - quit = TRUE - break - is $15 // -> - if octave < 3 - octave++ - showOctave + // + // Check for tone keys + // + for i = 0 to 13 + if keytone[i] == key + if LFO == 0 + hilopwm(scale[i]>>octave, LFO, 0) + else + hilopwm(scale[i]>>octave, LFO, LFOmap) fin break - is $08 // <- - if octave > 0 - octave-- - showOctave + fin + next + // + // Check for macro keys + // + if i > 13 + for i = 0 to 6 + if keymacro[i] == key + playback(i) + break fin - break - is '1' - is '2' - is '3' - is '4' - is '5' - is '6' - is '7' - is '8' - LFOmap = key - '1' - showWaveform - break - is '<' - is ',' - LFO-- - showLFO - break - is '>' - is '.' - LFO++ - showLFO - break - is '+' - is $0B // UP - if duration < 40 - duration++ - recalcEnv - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) - showDuration - fin - break - is '-' - is $0A // DOWN - if duration > 2 - duration-- - recalcEnv - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) - showDuration - fin - break - otherwise - for i = 0 to 13 - if keytone[i] == key - if LFO == 0 - hilopwm(scale[i]>>octave, LFO, 0) - else - hilopwm(scale[i]>>octave, LFO, LFOmap) + next + if i > 6 + if not recording + for i = 0 to 6 + if keyrecord[i] == key + recording = (key << 8) | i + // + // Save current state + // + record.absStart = TRUE + record.durAtk = atkLen + record.durDcy = dcyLen + record.durSus = susLen + record.durRel = relLen + record.rateAtk = atkRate + record.rateDcy = dcyRate + record.rateRel = relRate + record.idxOctave = octave + record.perLFO = LFO + record.idxLFO = LFOmap + record.sequence = 0 + flash + putsxy(29, 3, "RECORDING") + inverse + key = 0 + break fin - break - fin - next - wend + next + fin + if i > 6 + when key + is $1B // ESC + if recording // Cancel recording + recording = FALSE + putsxy(29, 3, " ") + else + quit = query("QUIT (Y/N)?") + if not quit + showMainPanel + fin + fin + break + is '?' + record.absStart = FALSE + is '/' + if recording // Copy recorded macro to key macro + memcpy(macros + t_macro * (recording & $FF), @record, t_macro) + recording = FALSE + modPatch = TRUE + putsxy(29, 3, " ") + fin + break + is $15 // -> + if octave < 3 + octave++ + showOctave + else + key = 0 + fin + break + is $08 // <- + if octave > 0 + octave-- + showOctave + else + key = 0 + fin + break + is '1' + is '2' + is '3' + is '4' + is '5' + is '6' + is '7' + is '8' + LFOmap = key - '1' + showWaveform + break + is '<' + is ',' + LFO-- + showLFO + break + is '>' + is '.' + LFO++ + showLFO + break + is '+' + is $0B // UP + if duration < 40 + duration++ + recalcEnv + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + showDuration + else + key = 0 + fin + break + is '-' + is $0A // DOWN + if duration > 1 + duration-- + recalcEnv + envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + showDuration + else + key = 0 + fin + break + is 'P' + if modPatch + savePatch + fin + break + wend + fin + fin + fin + if recording and key + if record.sequence < 255 + record.sequence++ + record.sequence[record.sequence] = key + fin + fin fin - //LFO = pdl(0) until quit end // // Get heap start. // -heap = *freemem +macros = *freemem +heap = macros + t_macro * NMACROS +loadPatch +memset(macros, 0, t_macro * NMACROS) call($FDED, $8D, 0, 0, 0) call($FDED, $91, 0, 0, 0)// CTRL-Q = turn off 80 column call($FDED, $8D, 0, 0, 0) ^$C000 = 0 // Turn off 80STORE grmode -clearview -showDuration -showWaveform -showLFO -putsxy(8, 0, "OSCILLATION OVERTHRUSTER") -normal -putsxy(2, 0, "1..8") -gotoxy(34, 0); putc('<') -gotoxy(39, 0); putc('>') -gotoxy(6, 3); putc('-') -gotoxy(32, 3); putc('+') -inverse -showOctave -normal -putsxy(0, 2, "<-") -putsxy(38, 2, "->") -inverse -putsxy(11, 3, "A S D F G H J K L") -normal -gotoxy(14, 2); putc('E') -gotoxy(16, 2); putc('R') -gotoxy(20, 2); putc('Y') -gotoxy(22, 2); putc('U') -gotoxy(24, 2); putc('I') -inverse +showMainPanel main +if modPatch + if query("SAVE PATCH (Y/N)?") + savePatch + fin +fin normal textmode done diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 8578bcef5d8528894497e6f51c9d9539729f53cd..7246055c4575b7edcdc973746249c1971dc0d645 100755 GIT binary patch delta 3570 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 MQkOir^+{OwA9YOdT>t<8 diff --git a/src/samplesrc/a2pwm/makefile b/src/samplesrc/a2pwm/makefile index df9b77b..d5080af 100755 --- a/src/samplesrc/a2pwm/makefile +++ b/src/samplesrc/a2pwm/makefile @@ -24,5 +24,5 @@ clean: -rm *.o *~ *.a *.bin $(HILOPWM): a2pwm.s util.pla hilopwm.pla pwmvm.s $(PLASM) - ./$(PLASM) -A < hilopwm.pla > hilopwm.a + $(PLASM) -A < hilopwm.pla > hilopwm.a acme -o $(HILOPWM) pwmvm.s diff --git a/src/samplesrc/a2pwm/util.pla b/src/samplesrc/a2pwm/util.pla index 4ad9d8a..e4db7f2 100644 --- a/src/samplesrc/a2pwm/util.pla +++ b/src/samplesrc/a2pwm/util.pla @@ -22,6 +22,10 @@ word txt1scrn[] = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 // +// ProDOS error +// +byte perr +// // CALL 6502 ROUTINE // CALL(ADDR, AREG, XREG, YREG, STATUS) // @@ -63,225 +67,248 @@ CALL6502 JSR $FFFF REGVALS !FILL 4 end // +// CALL PRODOS +// SYSCALL(CMD, PARAMS) +// +asm syscall + LDA ESTKL,X + LDY ESTKH,X + STA PARAMS + STY PARAMS+1 + INX + LDA ESTKL,X + STA CMD + JSR $BF00 +CMD: !BYTE 00 +PARAMS: !WORD 0000 + LDY #$00 + STA ESTKL,X + STY ESTKH,X + RTS +end +// // SET MEMORY TO VALUE // MEMSET(ADDR, VALUE, SIZE) // With optimizations from Peter Ferrie // asm memset - LDA ESTKL+2,X - STA DSTL - LDA ESTKH+2,X - STA DSTH - LDY ESTKL,X - BEQ + - INC ESTKH,X - LDY #$00 -+ LDA ESTKH,X - BEQ SETMEX + LDA ESTKL+2,X + STA DSTL + LDA ESTKH+2,X + STA DSTH + LDY ESTKL,X + BEQ + + INC ESTKH,X + LDY #$00 ++ LDA ESTKH,X + BEQ SETMEX SETMLPL CLC - LDA ESTKL+1,X + LDA ESTKL+1,X SETMLPH STA (DST),Y - DEC ESTKL,X - BEQ ++ -- INY - BEQ + --- BCS SETMLPL - SEC - LDA ESTKH+1,X - BCS SETMLPH -+ INC DSTH - BNE -- -++ DEC ESTKH,X - BNE - + DEC ESTKL,X + BEQ ++ +- INY + BEQ + +-- BCS SETMLPL + SEC + LDA ESTKH+1,X + BCS SETMLPH ++ INC DSTH + BNE -- +++ DEC ESTKH,X + BNE - SETMEX INX - INX - RTS + INX + RTS end // // COPY MEMORY // MEMCPY(DSTADDR, SRCADDR, SIZE) // asm memcpy - INX - INX - LDA ESTKL-2,X - ORA ESTKH-2,X - BEQ CPYMEX - LDA ESTKL-1,X - CMP ESTKL,X - LDA ESTKH-1,X - SBC ESTKH,X - BCC REVCPY + INX + INX + LDA ESTKL-2,X + ORA ESTKH-2,X + BEQ CPYMEX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BCC REVCPY ; ; FORWARD COPY ; - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL-1,X - STA SRCL - LDA ESTKH-1,X - STA SRCH - LDY ESTKL-2,X - BEQ FORCPYLP - INC ESTKH-2,X - LDY #$00 + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL-1,X + STA SRCL + LDA ESTKH-1,X + STA SRCH + LDY ESTKL-2,X + BEQ FORCPYLP + INC ESTKH-2,X + LDY #$00 FORCPYLP LDA (SRC),Y - STA (DST),Y - INY - BNE + - INC DSTH - INC SRCH -+ DEC ESTKL-2,X - BNE FORCPYLP - DEC ESTKH-2,X - BNE FORCPYLP - RTS + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL-2,X + BNE FORCPYLP + DEC ESTKH-2,X + BNE FORCPYLP + RTS ; ; REVERSE COPY ; REVCPY ;CLC - LDA ESTKL-2,X - ADC ESTKL,X - STA DSTL - LDA ESTKH-2,X - ADC ESTKH,X - STA DSTH - CLC - LDA ESTKL-2,X - ADC ESTKL-1,X - STA SRCL - LDA ESTKH-2,X - ADC ESTKH-1,X - STA SRCH - DEC DSTH - DEC SRCH - LDY #$FF - LDA ESTKL-2,X - BEQ REVCPYLP - INC ESTKH-2,X + LDA ESTKL-2,X + ADC ESTKL,X + STA DSTL + LDA ESTKH-2,X + ADC ESTKH,X + STA DSTH + CLC + LDA ESTKL-2,X + ADC ESTKL-1,X + STA SRCL + LDA ESTKH-2,X + ADC ESTKH-1,X + STA SRCH + DEC DSTH + DEC SRCH + LDY #$FF + LDA ESTKL-2,X + BEQ REVCPYLP + INC ESTKH-2,X REVCPYLP LDA (SRC),Y - STA (DST),Y - DEY - CPY #$FF - BNE + - DEC DSTH - DEC SRCH -+ DEC ESTKL-2,X - BNE REVCPYLP - DEC ESTKH-2,X - BNE REVCPYLP + STA (DST),Y + DEY + CPY #$FF + BNE + + DEC DSTH + DEC SRCH ++ DEC ESTKL-2,X + BNE REVCPYLP + DEC ESTKH-2,X + BNE REVCPYLP CPYMEX RTS end // // Unsigned word comparisons. // asm uword_isge - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isle - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isgt - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_islt - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end // // Addresses of internal routines. // asm _hilopwm - TXA - PHA - JSR HILOPWM - PLA - TAX - DEX - RTS + TXA + PHA + JSR HILOPWM + PLA + TAX + DEX + RTS end asm toupper - LDA ESTKL,X + LDA ESTKL,X TOUPR AND #$7F - CMP #'a' - BCC + - CMP #'z'+1 - BCS + - SBC #$1F -+ STA ESTKL,X - RTS + CMP #'a' + BCC + + CMP #'z'+1 + BCS + + SBC #$1F ++ STA ESTKL,X + RTS end // // CONSOLE I/O // asm putc - LDA ESTKL,X -; JSR TOUPR - ORA #$80 - JMP $FDF0 + LDA ESTKL,X +; JSR TOUPR + ORA #$80 + JMP $FDF0 end asm getc - DEX -- LDA $C000 - BPL - - BIT $C010 - AND #$7F - STA ESTKL,X - LDA #$00 - STA ESTKH,X - RTS + DEX +- LDA $C000 + BPL - + BIT $C010 + AND #$7F + STA ESTKL,X + LDA #$00 + STA ESTKH,X + RTS end def keypressed return ^$C000 >= 128 end def pdl(num) return call($FB1E, 0, num, 0, 0)->2 -end +end def bttn(num) return (^$C061+num) >= 128 end def putln return putc($0D) end +def beep + return putc($07) +end def puts(str) byte i @@ -320,6 +347,9 @@ end def inverse ^$32 = $3F end +def flash + ^$32 = $1F +end def gotoxy(x, y) ^$24 = x + ^$20 return call($FB5B, y + ^$22, 0, 0, 0) @@ -341,7 +371,7 @@ end def clearview byte i word c - inverse + c = ' ' | $80 & ^$32 c = c | (c << 8) for i = ^$22 to ^$23 @@ -385,6 +415,71 @@ def rect(left, right, top, bottom, fill) fin end // +// ProDOS routines +// +def open(path, buff) + byte params[6] + + params.0 = 3 + params:1 = path + params:3 = buff + params.5 = 0 + perr = syscall($C8, @params) + return params.5 +end +def close(refnum) + byte params[2] + + params.0 = 1 + params.1 = refnum + perr = syscall($CC, @params) + return perr +end +def read(refnum, buff, len) + byte params[8] + + params.0 = 4 + params.1 = refnum + params:2 = buff + params:4 = len + params:6 = 0 + perr = syscall($CA, @params) + return params:6 +end +def write(refnum, buff, len) + byte params[8] + + params.0 = 4 + params.1 = refnum + params:2 = buff + params:4 = len + params:6 = 0 + perr = syscall($CB, @params) + return params:6 +end +def create(path, access, type, aux) + byte params[12] + + params.0 = 7 + params:1 = path + params.3 = access + params.4 = type + params:5 = aux + params.7 = $1 + params:8 = 0 + params:10 = 0 + perr = syscall($C0, @params) + return perr +end +def destroy(path) + byte params[3] + + params.0 = 1 + params:1 = path + perr = syscall($C1, @params) + return perr +end +// // HFO/LFO PWM sound routines // def envelope(attack, decay, sustain, release, ainc, dinc, rinc) From c180c6e5447f2412988b713d942490e26a888546 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 25 Apr 2017 23:10:43 -0700 Subject: [PATCH 22/58] Update startup --- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 7246055c4575b7edcdc973746249c1971dc0d645..e5bbdca81d6d899f0c70fb829b044dd3fd9f1815 100755 GIT binary patch delta 271 zcmZp8z|ru4V?#O%Z^Nb}1<+IEMuJC`9S{D(ET%hd2g>DEK-$2l*=m zxjOp?xhOGQ<7@&eQ`c8l00WRR{~%WdN2g$jQYD68oIMaV_GoH?Tzz0_~mCMxWn1Qu+~xKf>NN;IS^H- hbfkfSk?Rh_88$O={AX+`TUN%n3jiiW8vXzP From e6b068cee5a2c84650c97cb6c7b81bea3ef63245 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 26 Apr 2017 10:23:13 -0700 Subject: [PATCH 23/58] Release 1.0 --- src/samplesrc/a2pwm/hilopwm.pla | 263 +++++++++++++++++--------------- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes src/samplesrc/a2pwm/util.pla | 8 +- 3 files changed, 148 insertions(+), 123 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index c4e937c..2fd6a22 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -1,14 +1,13 @@ const inbuff = $200 const freemem = $0002 -const iobuffer = 0x1800 +const iobuffer = $1C00 const NMACROS = 7 const FALSE = 0 const TRUE = !FALSE // -// Macro sequence structure +// Patch state // -struc t_macro - byte absStart +struc t_state byte durAtk byte durDcy byte durSus @@ -16,14 +15,23 @@ struc t_macro word rateAtk word rateDcy word rateRel - byte idxOctave - byte perLFO + byte octave + byte LFO byte idxLFO - byte[256] sequence end +// +// Macro sequence structure +// +struc t_macro + byte absStart + byte stateStart[t_state] + byte sequence[256] +end +byte current[t_state] // Current state word macros // Pointer to macros byte record[t_macro] // Recording buffer word recording = FALSE // Recording key/flag +byte playing = 0 // Keep track of active macros // // System variables. // @@ -45,27 +53,9 @@ byte keymacro[] = 'Z', 'X', 'C', 'V', 'B', 'N', 'M' // byte keyrecord[] = $1A, $18, $03, $16, $02, $0E, $0D // -// Which octave are we in -// -byte octave = 1 -// -// FLO period and waveform -// -byte LFO, LFOmap -// // Note duration // -byte duration = 22 -// -// Envelope parameters -// -byte atkLen = 2 -byte dcyLen = 0 -byte susLen = 4 -byte relLen = 16 -word atkRate = $07FF -word dcyRate = $0000 -word relRate = $00FF +byte duration = 16 // // Patch filename // @@ -80,33 +70,35 @@ include "util.pla" // def loadPatch byte refnum - + refnum = open(@patch, iobuffer) if refnum read(refnum, macros, t_macro * NMACROS) // Macros - read(refnum, @octave, @patch - @octave) // Initial values + read(refnum, @current, t_state) // Initial values close(refnum) fin + return refnum <> 0 end def savePatch byte refnum - + destroy(@patch) create(@patch, $C3, $06, $00) // full access, BIN file refnum = open(@patch, iobuffer) if refnum write(refnum, macros, t_macro * NMACROS) // Macros - write(refnum, @octave, @patch - @octave) // Initial values + write(refnum, @current, t_state) // Initial values close(refnum) modPatch = FALSE fin + return refnum <> 0 end // // Query routines // def query(str) byte c - + inverse clearview putsxy(20 - ^str / 2, 2, str) @@ -119,7 +111,7 @@ end def showLFO byte LFObar - LFObar = (LFO+7)/8 + LFObar = (current.LFO+7)/8 grcolor(WHITE) rect(33, 39, 6, 39, FALSE) if LFObar < 32 @@ -135,7 +127,7 @@ def showLFO // putsxy(35, 0, " ") gotoxy(35, 0) - return puti(LFO) + return puti(current.LFO) end // // Display LFO waveform @@ -146,8 +138,8 @@ def showWaveform // // Get pointer to LFO waveform by calling PWM with zero note // - envelope(0, 0, 0, 0, atkRate, dcyRate, relRate) - hilopwm(0, LFO, LFOmap) + envelope(0, 0, 0, 0, current:rateAtk, current:rateDcy, current:rateRel) + hilopwm(0, current.LFO, current.idxLFO) mapPtr = *0 // Pointer at address 0 grcolor(WHITE) rect(0, 33, 6, 39, FALSE) @@ -163,7 +155,7 @@ def showWaveform // // Restore envelope // - return envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + return envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) end // // Display duration @@ -190,8 +182,8 @@ def showDuration // // Show actual value // - putsxy(5, 3, " ") - gotoxy(5, 3) + putsxy(4, 3, " ") + gotoxy(4, 3) return puti(duration) end // @@ -201,7 +193,7 @@ def showOctave inverse putsxy(0, 1, "----------------------------------------") normal - putsxy(octave*10, 1, "----------") + putsxy(current.octave*10, 1, "----------") return inverse end def showMainPanel @@ -216,7 +208,7 @@ def showMainPanel gotoxy(34, 0); putc('<') gotoxy(38, 0); putc('>') gotoxy(3, 3); putc('-') - gotoxy(8, 3); putc('+') + gotoxy(6, 3); putc('+') inverse showOctave normal @@ -232,22 +224,47 @@ def showMainPanel gotoxy(24, 2); putc('I') return inverse end +def showHelp + normal + home + putsxy(15, 0, "HELP") + putsxy(0, 1, "=======================================") + putsxy(2, 3, "KEY COMMAND") + putsxy(2, 4, "-------------- --------------------") + putsxy(2, 5, "ESC HELP/CANCEL RECORD") + putsxy(2, 6, "CTRL-Q QUIT") + putsxy(2, 7, "1..8 LFO WAVEFORM") + putsxy(2, 8, "< , INCREASE LFO") + putsxy(2, 9, "> . DECREASE LFO") + putsxy(2, 10, "LEFT-ARROW PREV OCTAVE") + putsxy(2, 11, "RIGHT-ARROW NEXT OCTAVE") + putsxy(2, 12, "+ UP-ARROW INCREASE DURATION") + putsxy(2, 13, "- DOWN-ARROW DECREASE DURATION") + putsxy(2, 14, "CTRL-Z..M RECORD MACRO") + putsxy(2, 15, "/ SAVE ABS MACRO") + putsxy(2, 16, "? SAVE REL MACRO") + putsxy(2, 17, "P PERSISTANT STATE") + putsxy(8, 23, "PRESS A KEY TO RETURN") + return getc +end // // Recalc envelope parameters // def recalcEnv - atkLen = duration/8 - relLen = duration/2 - susLen = duration - atkLen - relLen - atkRate = $0FFF/atkLen - relRate = $0FFF/relLen + current.durAtk = duration/8 + current.durDcy = 0 + current.durRel = duration/2 + current.durSus = duration - current.durAtk - current.durRel + current:rateAtk = $0FFF/current.durAtk + current:rateDcy = 0 + current:rateRel = $0FFF/current.durRel end // // Rest // def restnote byte d - + for d = duration downto 1 call($FCA8, $6A, 0, 0, 0) next @@ -255,33 +272,30 @@ end // // playback a sequence // -def playback(seq) +def playback(idx) word macro - byte seq, key, i, showUpdate - - macro = macros + t_macro * seq + byte seq, key, i + byte save[t_state] + + // + // Check for recursive playback + // + if playing & (1 << idx) + return + fin + playing = playing | (1 << idx) + macro = macros + t_macro * idx + // + // Save current state + // + memcpy(@save, @current, t_state) // // Start off with initial conditions // - showUpdate = 0 if macro->absStart - if macro->idxOctave <> octave - octave = macro->idxOctave - showUpdate = showUpdate | 1 - fin - if macro->idxLFO <> LFOmap - LFOmap = macro->idxLFO - showUpdate = showUpdate | 2 - fin - if macro->perLFO <> LFO - LFO = macro->perLFO - showUpdate = showUpdate | 4 - fin - if macro->durAtk + macro->durDcy + macro->durSus + macro->durRel <> duration - envelope(macro->durAtk, macro->durDcy, macro->durSus, macro->durRel, macro=>rateAtk, macro=>rateDcy, macro=>rateRel) - duration = macro->durAtk + macro->durDcy + macro->durSus + macro->durRel - showUpdate = showUpdate | 8 - fin + memcpy(@current, macro + stateStart, t_state) + duration = current.durAtk + current.durDcy + current.durSus + current.durRel + envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) fin // // Run throught the sequence @@ -294,9 +308,9 @@ def playback(seq) for i = 0 to 13 if keytone[i] == key if LFO == 0 - hilopwm(scale[i]>>octave, LFO, 0) + hilopwm(scale[i] >> current.octave, current.LFO, 0) else - hilopwm(scale[i]>>octave, LFO, LFOmap) + hilopwm(scale[i] >> current.octave, current.LFO, current.idxLFO) fin break fin @@ -317,12 +331,14 @@ def playback(seq) restnote break is $15 // -> - octave++ - showUpdate = showUpdate | 1 + if current.octave < 3 + current.octave++ + fin break is $08 // <- - showUpdate = showUpdate | 1 - octave-- + if current.octave > 1 + current.octave-- + fin break is '1' is '2' @@ -332,44 +348,47 @@ def playback(seq) is '6' is '7' is '8' - LFOmap = key - '1' - showUpdate = showUpdate | 2 + current.idxLFO = key - '1' break is '<' is ',' - LFO-- - showUpdate = showUpdate | 4 + if current.LFO > 0 + current.LFO-- + fin break is '>' is '.' - LFO++ - showUpdate = showUpdate | 4 + if current.LFO < 255 + current.LFO++ + fin break is '+' is $0B // UP - duration++ + if duration < 40 + duration++ + fin recalcEnv - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) - showUpdate = showUpdate | 8 + envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) break is '-' is $0A // DOWN - duration-- + if duration > 1 + duration-- + fin recalcEnv - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) - showUpdate = showUpdate | 8 + envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) break wend fin fin next // - // Udate display + // Restore state // - if showUpdate & 1; showOctave; fin - if showUpdate & 2; showWaveform; fin - if showUpdate & 4; showLFO; fin - if showUpdate & 8; showDuration; fin + memcpy(@current, @save, t_state) + duration = current.durAtk + current.durDcy + current.durSus + current.durRel + envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) + playing = playing & ~(1 << idx) end // // Main loop @@ -377,7 +396,6 @@ end def main byte quit, key, i - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) quit = FALSE repeat if keypressed @@ -387,10 +405,10 @@ def main // for i = 0 to 13 if keytone[i] == key - if LFO == 0 - hilopwm(scale[i]>>octave, LFO, 0) + if current.LFO == 0 + hilopwm(scale[i] >> current.octave, current.LFO, 0) else - hilopwm(scale[i]>>octave, LFO, LFOmap) + hilopwm(scale[i] >> current.octave, current.LFO, current.idxLFO) fin break fin @@ -413,17 +431,8 @@ def main // // Save current state // + memcpy(@record.stateStart, @current, t_state) record.absStart = TRUE - record.durAtk = atkLen - record.durDcy = dcyLen - record.durSus = susLen - record.durRel = relLen - record.rateAtk = atkRate - record.rateDcy = dcyRate - record.rateRel = relRate - record.idxOctave = octave - record.perLFO = LFO - record.idxLFO = LFOmap record.sequence = 0 flash putsxy(29, 3, "RECORDING") @@ -440,10 +449,16 @@ def main recording = FALSE putsxy(29, 3, " ") else - quit = query("QUIT (Y/N)?") - if not quit - showMainPanel - fin + textmode + showHelp + grmode + showMainPanel + fin + break + is $11 // CTRL-Q + quit = query("QUIT (Y/N)?") + if not quit + showMainPanel fin break is '?' @@ -457,16 +472,16 @@ def main fin break is $15 // -> - if octave < 3 - octave++ + if current.octave < 3 + current.octave++ showOctave else key = 0 fin break is $08 // <- - if octave > 0 - octave-- + if current.octave > 0 + current.octave-- showOctave else key = 0 @@ -480,17 +495,21 @@ def main is '6' is '7' is '8' - LFOmap = key - '1' + current.idxLFO = key - '1' showWaveform break is '<' is ',' - LFO-- + if current.LFO > 0 + current.LFO-- + fin showLFO break is '>' is '.' - LFO++ + if current.LFO < 255 + current.LFO++ + fin showLFO break is '+' @@ -498,7 +517,7 @@ def main if duration < 40 duration++ recalcEnv - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) showDuration else key = 0 @@ -509,7 +528,7 @@ def main if duration > 1 duration-- recalcEnv - envelope(atkLen, dcyLen, susLen, relLen, atkRate, dcyRate, relRate) + envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) showDuration else key = 0 @@ -528,6 +547,8 @@ def main if record.sequence < 255 record.sequence++ record.sequence[record.sequence] = key + else + beep fin fin fin @@ -538,8 +559,12 @@ end // macros = *freemem heap = macros + t_macro * NMACROS -loadPatch memset(macros, 0, t_macro * NMACROS) +if not loadPatch + showHelp +fin +recalcEnv +envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) call($FDED, $8D, 0, 0, 0) call($FDED, $91, 0, 0, 0)// CTRL-Q = turn off 80 column call($FDED, $8D, 0, 0, 0) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index e5bbdca81d6d899f0c70fb829b044dd3fd9f1815..c7c852db7b6231c120799d58ca8323fa547772c0 100755 GIT binary patch delta 9244 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 Za|$gP_@`T;CG)@4lDY4(BaaD({{`&jwnYE{ delta 12753 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 diff --git a/src/samplesrc/a2pwm/util.pla b/src/samplesrc/a2pwm/util.pla index e4db7f2..7c08fd4 100644 --- a/src/samplesrc/a2pwm/util.pla +++ b/src/samplesrc/a2pwm/util.pla @@ -491,9 +491,9 @@ def envelope(attack, decay, sustain, release, ainc, dinc, rinc) *$12 = dinc *$14 = rinc end -def hilopwm(HFO, LFO, LFOusr) - ^$08 = HFO - ^$09 = LFO - *$0A = LFOusr +def hilopwm(hfo, lfo, usr) + ^$08 = hfo + ^$09 = lfo + *$0A = usr return _hilopwm end From f1eb872c45394a844bfb7da3f551d29f655a0da0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 26 Apr 2017 10:32:02 -0700 Subject: [PATCH 24/58] Create readme.md --- src/samplesrc/a2pwm/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/samplesrc/a2pwm/readme.md diff --git a/src/samplesrc/a2pwm/readme.md b/src/samplesrc/a2pwm/readme.md new file mode 100644 index 0000000..2ccc181 --- /dev/null +++ b/src/samplesrc/a2pwm/readme.md @@ -0,0 +1 @@ +HiLoPWM is a synthesizer/sequencer for playing around with the Apple II and its limited sound capability From 4a5e3ff989d45b2c4798a048a4fdb113df493e04 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 26 Apr 2017 14:34:38 -0700 Subject: [PATCH 25/58] Initial documentation --- src/samplesrc/a2pwm/readme.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/readme.md b/src/samplesrc/a2pwm/readme.md index 2ccc181..a553ab1 100644 --- a/src/samplesrc/a2pwm/readme.md +++ b/src/samplesrc/a2pwm/readme.md @@ -1 +1,27 @@ -HiLoPWM is a synthesizer/sequencer for playing around with the Apple II and its limited sound capability +# Oscillation Overthruster +## Intro +Oscillation Overthruster (HiLoPWM) is a synthesizer/sequencer for playing around with the Apple II and its limited sound capability. A High Frequency Oscillator (HFO) samples the waveform of a Low Frequency Oscillator (LFO) and applies an Attack/Decay/Sustain/Release envelope to the resulting value which is output as a Pulse Width Modulated (PWM) value. This can create some interesting effects and tones. +## Running +The HILOPWM.SYSTEM file can be launched by booting the lfo.po disk image. The first time, the help screen will be presented with a list of the available commands. Once a PATCH file has been saved, the help screen will only show up by pressing the ESCape key. The main screen displays a graphical representation of the LFO waveform, LFO period and tone duration. The lower panel displays the textual representation of the LFO period, duration, and octave. The Apple II keyboard keys that map a piano keyboard octave is shown in the middle. Macros can be recorded and played back along with playing tones and changing parameters. The macros and parameters can be made persistent by saving them to disk. The next time HILOPWM.SYSTEM is run, the help screen will be skipped and the macros and settings from the previous session will be present. When quitting (CTRL-Q), you will be prompted if want to quit in case it was an accidental keypress, then optionally prompted to save the current state if it has changed since the last save. +## Playing Tones +The Apple II keyboard is mapped to a one octave piano keyboard, plus one note on either side of the octave; from Bn-1 to An+1. +## Command keys + KEY COMMAND + -------------- -------------------- + ESC HELP/CANCEL RECORD + CTRL-Q QUIT + 1..8 LFO WAVEFORM + < , INCREASE LFO + > . DECREASE LFO + LEFT-ARROW PREV OCTAVE + RIGHT-ARROW NEXT OCTAVE + + UP-ARROW INCREASE DURATION + - DOWN-ARROW DECREASE DURATION + CTRL-Z..M RECORD MACRO + / SAVE ABS MACRO + ? SAVE REL MACRO + P PERSISTANT STATE + +Command keys and note keys can be interspersed together. +### Recording Macros +One of the most powerful features of the Oscillation Overthruster is macro recording. There are seven macros that can be assigned to the lower row of keys, Z ... M. To record one of the macros, type the key along with the CONTROL key to begin recording. The RECORDING text will show up to the right of the text panel during recording. When recording, other macros can be called, allowing nested calls. However, recursive macros cannot be made, i.e. macro Z calling macro X calling macro Z. If, during recording, you want to cancel the macro, press ESCape. Their are two ways to save the macro: absolute and relative. An absolute macro will retain the state settings at the time the macro is recorded. Octave, duration, and LFO settings are restored before the macro is played, then restored when it is done. A relative macro will use the current settings when playing back. You can make the current macros persistent by pressing 'P' to write the macros and current settings to disk for the next time. From 68053fb5fc9bfc5cde4909a529cdbead943c5739 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Wed, 26 Apr 2017 14:36:16 -0700 Subject: [PATCH 26/58] Version 1.1 with docs and LFO from 0 to 32 --- src/samplesrc/a2pwm/._demo.po | Bin 4096 -> 0 bytes src/samplesrc/a2pwm/._lfo.po | Bin 4096 -> 0 bytes src/samplesrc/a2pwm/hilopwm.pla | 17 ++++++------- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes src/samplesrc/a2pwm/pwmvm.s | 42 +++++++++----------------------- 5 files changed, 18 insertions(+), 41 deletions(-) delete mode 100755 src/samplesrc/a2pwm/._demo.po delete mode 100755 src/samplesrc/a2pwm/._lfo.po diff --git a/src/samplesrc/a2pwm/._demo.po b/src/samplesrc/a2pwm/._demo.po deleted file mode 100755 index c29b0e3e8045b52c1f28b7dd7da78f57370be2ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIgo;|%-Cq47!KeV z5)#CmaDEX)2g3}YGG;WTj6gnATqHR^SFbFysH8M8Co@y8EI%hNA84(q37VEs?q~>% zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2;dI^P-hc_!9Xq~BePhcD784hv?w`M zAuYcsTOl*ABsH%jGe0jeC#O;&CpE1^At@&@FB{m?h3Xp86srH>UXfvt`~M#R-1aD8 diff --git a/src/samplesrc/a2pwm/._lfo.po b/src/samplesrc/a2pwm/._lfo.po deleted file mode 100755 index d5a959f9b4ffeab05290e7a33c76704157a98fbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIgo;|%-Cq47!KeV z5)#CmaDF932g3}YGG;WTj6gnATqHR^SFbFysH8M8Co@y8EI%hNA84(q37VEs?q~>% zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2;dI^P-hc_!9Xq~BePhcD784hv?w`M zAuYcsTOl*ABsH%jGe0jeC#O;&CpE1^At@&@FB{m?h3Xp86srH>UXfvt`~M#RN{A?E diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 2fd6a22..015f750 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -109,18 +109,15 @@ end // Display LFO bar // def showLFO - byte LFObar - - LFObar = (current.LFO+7)/8 grcolor(WHITE) rect(33, 39, 6, 39, FALSE) - if LFObar < 32 + if current.LFO < 32 grcolor(ORANGE) - rect(34, 38, 7, 38-LFObar, TRUE) + rect(34, 38, 7, 38-current.LFO, TRUE) fin - if LFObar + if current.LFO grcolor(DRKBLU) - rect(34, 38, 39-LFObar, 38, TRUE) + rect(34, 38, 39-current.LFO, 38, TRUE) fin // //Show actual value @@ -202,7 +199,7 @@ def showMainPanel showDuration showWaveform showLFO - putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.0") + putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.1") normal putsxy(1, 0, "1-8") gotoxy(34, 0); putc('<') @@ -358,7 +355,7 @@ def playback(idx) break is '>' is '.' - if current.LFO < 255 + if current.LFO < 32 current.LFO++ fin break @@ -507,7 +504,7 @@ def main break is '>' is '.' - if current.LFO < 255 + if current.LFO < 32 current.LFO++ fin showLFO diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index c7c852db7b6231c120799d58ca8323fa547772c0..c99952b73db8a2fc5b45fd822fcc3b204c6970bf 100755 GIT binary patch delta 3563 zcmb7GT})iZ6+Sb&ToxAA7z4%_;|1bnJ>0!J{5Zy#Y#_#NNN=4RdXa#*_S(K)uQ9E# zgWMI7vZyL*9zyzaork0kNgH8>2e(d$AKI$TMwZex$^)$;RjpLXPU6N&8Uj|D;vYiK z%)PtbxWrZWVfOsbnK|D%b0;tRCNKLg9QT$r*TV}9TLJ*@Lr@TN-}O#^gRIOI^gro) znNZ@JDL&_)FZ?;PpB`@R3eS`-mQQV-g^sJ`Q`NI@b;H!AU|V=5u;>@kscMH^mo=)8 zMwL=(e>&W8|ic`cl(dTjmv&XLM+`A9#H8hPy1#Aa0*}{D*dC zNO|o*C9P`ya)cS*)E2a{UmdEnyAM|0OFemSb>^PxpB$>JQtz?#q4G^ajR(m)UVd_u zu0>XjmUsdA7MVlkwQFo4?q;b;f3$m!&<0|c9Zo9R#doLAYW7oyYnruZFKExaswJmi z)6QL<{pCyAbD6XA;W*&$V&?Vv>ECP5{6V{RF*E&^Hh1Z;kB}z&og;l=jZqpO4hDjQ zl&FU@@dQvd`LGbMQu9jmfFKHyupc;DL!$QJ(MiJXzaH({p$Qvx@V3~%d_oh3gNi2s z32H8Lp75G6E-iN5axJ*IvBiGGV&Bp%s5`=fahf2kK5ouy+<0%5W0YmbBbxJ2yK^Ku z%PlZVYdPVDlzDrp3d;!!D8xMMKUo{wWNw%ZizMin8W#2muh2>de}TvnGyHQ4mz08( zz4=%}Z3{O(S>;9*S|^kQm>;2mpeR!I(6PD(Ep=M6ikxi;BjYpy;~w@-n3{7!l{~H4 zZyeiP^mbTr1om%_HF$-_e*ajc(KV6o1+M!U4|_A;y)CgP9hDXYLc28;YRvND+giAJEo#n3$EiixP`B8htuxP~T|H}J z3TpzBw({f+l?C_dn}HQcT>}fTLKZ@?S6y9oErgny=hNsb^i4v`Lav@Qg60VZgJMUd z1;|iu9^w)fUV#W0xvq|UrjC5Bn(b{IP@TMq7DygBL!G1mv&!ZKqrkRy3_wYOT0rB> zQ#(!ovrBW4nnk=8Fd|CN8Ief~87gv8kCbk6q!^W&k`_XNKg><#X-mrs-&cMiY;h#3R}+bcttxm>^GDqLk}L%A#fyez)8c|I?%ii@6`?5-99-IB`x+(N4Dbnn-LY)Ya^@C%&}RxKe)2vv9FXgTTwgrdh>}Zk{qW>=q}Pv%b@!;SjE{zJ{efJ6F&akt zFQawX3D{gBF#!#qFSVdT3Q;9-l3Ef3;>?Q>^QIP6b#)zbzKQE9OnfG}CFDL=L3Ric zkV3?h&TpXi8?eW;fXHetX+-%~ELGD(KdC0`o(+UJao# zDMM`5ViSXCVPoT6Qn$5@0x&MFa!X;Qz4{n|QH3cTwNMgLb7B2pDds?@9sf@Cj@C|Y z+)r3#tP%wBJ^S<`L6oGHRilnDpDQQ5jyxdbioJNMD_sg!0c-K5ZmP!bfOW-i-$Gz& ztU}BgY*37ILk*;EsK$%HVy;>f@tn~o^(8`|2G;EA{jpYO6v#X}wGzB5b7|Ka(-Ayuk_A3W6~73(f9?&iiHdRk8-7*p_&Cqc?CkkL5)YuF!N?q z@AJ4X0agK#(9wrgsM9R`zOYEQ-XZTPTU`{cQQbSzyz0J=)uqf%jFqKx!LXzhOUgy{ zuSmVptDmJKel4gU1hKs$279P2=h2H3lKE;ZS~cOaY@>w#^c>P`wL+nx z6@2^;647BI0g-smnrS>K0KPQ~@UkqxO&qd#3UQVp0rfheK;%jTfpj#mKRmTRt%^x+ z{4*cr)pw&D9|CUtF(2uh{tM~SW+or)U0Jk81o0JUFTL}IS5u~U^#td}W!SP+y zFWiRVwD_o@M<#BmxeqWp5fCF0+|M!mh&5AfvZA8;Yqqf4gz6_NY}%c@g8p$Hos&Zb z#R>3Mzuo}T~r_pi*pG4IDYkeXU?4=zy1%uIr7^8 delta 74 zcmZp8z|ru4V?#QNfUyF@EF}Rh28PEB3LwVja+Y3SM)u9DLDd|a8yW)mcv-ZV^_UbC cLR1Y5v{)wJ?YqUuws}Xt2TxPkvNFb9032o(T>t<8 diff --git a/src/samplesrc/a2pwm/pwmvm.s b/src/samplesrc/a2pwm/pwmvm.s index c3c11a0..b23e653 100755 --- a/src/samplesrc/a2pwm/pwmvm.s +++ b/src/samplesrc/a2pwm/pwmvm.s @@ -57,43 +57,15 @@ HIMEM = $73 ;* INTERPRETER HEADER+INITIALIZATION ;* *= $2000 - STY IFPL ; INIT FRAME POINTER - LDA #$BF - STA IFPH - LDA #SEGEND - STA SRCH - LDA #$4C - CMP $BE00 ; CHECK FOR BASIC.SYSTEM - BNE + - CMP $BE03 - BNE + - LDA HIMEM - STA IFPL - LDA HIMEM+1 - STA IFPH - LDX #$00 ; SAVE PAGE ZERO -- LDA $00,X - STA ZPSAVE,X - INX - BNE - - JSR VMINIT - LDX #$00 ; RESTORE ZP -- LDA ZPSAVE,X - STA $00,X - INX - BNE - - RTS -+ LDX #$FE + LDX #$FE TXS JSR VMINIT JSR $BF00 !BYTE $65 !WORD EXITTBL EXITTBL: - !BYTE 4 - !BYTE 0 + !BYTE 4 + !BYTE 0 ;* ;* SYSTEM INTERPRETER ENTRYPOINT ;* @@ -990,6 +962,14 @@ VMINIT LDY #$10 ; INSTALL PAGE 0 FETCHOP ROUTINE STA DROP-1,Y DEY BNE - + STY IFPL ; INIT FRAME POINTER + LDA #$BF + STA IFPH + LDA #SEGEND + STA SRCH + LDA #$4C JMP START PAGE0 = * !PSEUDOPC $00EF { From f0382f93df03583a6542177b037ad174f5208df0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 26 Apr 2017 20:07:53 -0700 Subject: [PATCH 27/58] Add rest note recording --- src/samplesrc/a2pwm/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/readme.md b/src/samplesrc/a2pwm/readme.md index a553ab1..725e771 100644 --- a/src/samplesrc/a2pwm/readme.md +++ b/src/samplesrc/a2pwm/readme.md @@ -24,4 +24,4 @@ The Apple II keyboard is mapped to a one octave piano keyboard, plus one note on Command keys and note keys can be interspersed together. ### Recording Macros -One of the most powerful features of the Oscillation Overthruster is macro recording. There are seven macros that can be assigned to the lower row of keys, Z ... M. To record one of the macros, type the key along with the CONTROL key to begin recording. The RECORDING text will show up to the right of the text panel during recording. When recording, other macros can be called, allowing nested calls. However, recursive macros cannot be made, i.e. macro Z calling macro X calling macro Z. If, during recording, you want to cancel the macro, press ESCape. Their are two ways to save the macro: absolute and relative. An absolute macro will retain the state settings at the time the macro is recorded. Octave, duration, and LFO settings are restored before the macro is played, then restored when it is done. A relative macro will use the current settings when playing back. You can make the current macros persistent by pressing 'P' to write the macros and current settings to disk for the next time. +One of the most powerful features of the Oscillation Overthruster is macro recording. There are seven macros that can be assigned to the lower row of keys, Z ... M. To record one of the macros, type the key along with the CONTROL key to begin recording. The RECORDING text will show up to the right of the text panel during recording. When recording, other macros can be called, allowing nested calls. However, recursive macros cannot be made, i.e. macro Z calling macro X calling macro Z. If, during recording, you want to cancel the macro, press ESCape. Their are two ways to save the macro: absolute and relative. An absolute macro will retain the state settings at the time the macro is recorded. Octave, duration, and LFO settings are restored before the macro is played, then restored when it is done. A relative macro will use the current settings when playing back. To record a rest, the spacebar will insert a pause for the length of the current duration. You can make the current macros persistent by pressing 'P' to write the macros and current settings to disk for the next time. From 5d53c14101a0b4b64d7dd9f1d3453b974b80093a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 26 Apr 2017 20:43:10 -0700 Subject: [PATCH 28/58] Fix playback previous octave --- src/samplesrc/a2pwm/hilopwm.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 015f750..866bc2e 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -333,7 +333,7 @@ def playback(idx) fin break is $08 // <- - if current.octave > 1 + if current.octave > 0 current.octave-- fin break From 3d7a60fd2b0e1437c6f11b4cf50f263af9aa1a95 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Wed, 26 Apr 2017 22:04:37 -0700 Subject: [PATCH 29/58] Fix playback when LFO == 0 --- src/samplesrc/a2pwm/hilopwm.pla | 6 +++--- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 866bc2e..75937a1 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -304,8 +304,8 @@ def playback(idx) // for i = 0 to 13 if keytone[i] == key - if LFO == 0 - hilopwm(scale[i] >> current.octave, current.LFO, 0) + if current.LFO == 0 + hilopwm(scale[i] >> current.octave, 0, 0) else hilopwm(scale[i] >> current.octave, current.LFO, current.idxLFO) fin @@ -403,7 +403,7 @@ def main for i = 0 to 13 if keytone[i] == key if current.LFO == 0 - hilopwm(scale[i] >> current.octave, current.LFO, 0) + hilopwm(scale[i] >> current.octave, 0, 0) else hilopwm(scale[i] >> current.octave, current.LFO, current.idxLFO) fin diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index c99952b73db8a2fc5b45fd822fcc3b204c6970bf..5cae115a8aba72cacf7df8994bb615b99407a41f 100755 GIT binary patch delta 285 zcmZp8z|ru4V?#QNfVv{XEG27E28PEB3LwVja+Y3S#-E#6gP!v-c{^-oWKv?>ERb}J zhw;kfhm(a>+!=V(}n$v!2Gj2|YSD=`ufbDa5(q2t2$mWM0%w?10=bFx6`hsgp=EKOz0${2S6 E0QP)Wr2qf` delta 270 zcmZp8z|ru4V?#QNfVLvTEG1b!28PEB3LwVja+Y3S#=o0cgP!v-`8#Z8WKv?>ERb}J zXYzx|k_vh$Y)lC$tPVcr3|ia_4n7hLY64)fj2}8O89#L<^W`gYZT)YM!luRR;!`l$ zGGA+Q-V`nkBP)XdGe#{@J5dIpN-btLA5IX1r{afBfE=S12UMJK^OSrMMn>hyD+@x* zJefmY=!aa;FJWZJVbbEY@MPdolhaFK0y==v!N-CDXdT=IKtY%b3=0(}CrlIDoKbk6 uiE+bZkCH~lPm@oT7zs!@&V0wvap8N*! Date: Thu, 27 Apr 2017 13:12:42 -0700 Subject: [PATCH 30/58] Table of keys to notes --- src/samplesrc/a2pwm/readme.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/readme.md b/src/samplesrc/a2pwm/readme.md index 725e771..68d9910 100644 --- a/src/samplesrc/a2pwm/readme.md +++ b/src/samplesrc/a2pwm/readme.md @@ -4,7 +4,25 @@ Oscillation Overthruster (HiLoPWM) is a synthesizer/sequencer for playing around ## Running The HILOPWM.SYSTEM file can be launched by booting the lfo.po disk image. The first time, the help screen will be presented with a list of the available commands. Once a PATCH file has been saved, the help screen will only show up by pressing the ESCape key. The main screen displays a graphical representation of the LFO waveform, LFO period and tone duration. The lower panel displays the textual representation of the LFO period, duration, and octave. The Apple II keyboard keys that map a piano keyboard octave is shown in the middle. Macros can be recorded and played back along with playing tones and changing parameters. The macros and parameters can be made persistent by saving them to disk. The next time HILOPWM.SYSTEM is run, the help screen will be skipped and the macros and settings from the previous session will be present. When quitting (CTRL-Q), you will be prompted if want to quit in case it was an accidental keypress, then optionally prompted to save the current state if it has changed since the last save. ## Playing Tones -The Apple II keyboard is mapped to a one octave piano keyboard, plus one note on either side of the octave; from Bn-1 to An+1. +The Apple II keyboard is mapped to a one octave piano keyboard, from Bn-1 to Cn+1. + + KEY NOTE ('n' is current octave) + --- ---- + A Bn-1 + S Cn + E C#n + D Dn + R D#n + F En + G Fn + Y F#n + H Gn + U G#n + J An + I A#n + K Bn + L Cn+1 + ## Command keys KEY COMMAND -------------- -------------------- From 73574a9ba516570a9eea18e1272fdbaef97de2e2 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 27 Apr 2017 13:30:32 -0700 Subject: [PATCH 31/58] Add speaker phase adjust --- src/samplesrc/a2pwm/hilopwm.pla | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 75937a1..1770f01 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -199,7 +199,7 @@ def showMainPanel showDuration showWaveform showLFO - putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.1") + putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.1a") normal putsxy(1, 0, "1-8") gotoxy(34, 0); putc('<') @@ -241,6 +241,7 @@ def showHelp putsxy(2, 15, "/ SAVE ABS MACRO") putsxy(2, 16, "? SAVE REL MACRO") putsxy(2, 17, "P PERSISTANT STATE") + putsxy(2, 18, "0 TOGGLE PHASE") putsxy(8, 23, "PRESS A KEY TO RETURN") return getc end @@ -536,6 +537,9 @@ def main savePatch fin break + is '0' // Toggle speaker phase + ^$C030 + break wend fin fin From d51f737af28b8c8856cca0ddebe63569c03f655e Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 27 Apr 2017 13:32:05 -0700 Subject: [PATCH 32/58] Add speaker phase adjust --- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 5cae115a8aba72cacf7df8994bb615b99407a41f..b7166d86b42610659b0fb149c0b58e75fdb51a96 100755 GIT binary patch delta 370 zcmZp8z|ru4V?#QNK$IfGY$XL=28PEB3LwVja+Y3SCLPDkY(dZXnCcuhGcqYLZWc&# z=3tba9M><+WSF?QAS<3(o=HncPuf5M1%&v!yZg8*1b8?GZ$6pZ#VB2EWe~v15b*H7 zK?<7|n~RSNV+yO5f*mJANW|p4{F_YTR+H}*OHEELP=qlT6vQ%yO#TNX&rFUfloCWT zfeB>7!pZH0S&U|rKNafodYc=BOfWPEu`n|T_&r&tNSX2a7&rss0LVIbu>b%7 delta 361 zcmZp8z|ru4V?#QNfVv{XEG27E28PEB3LwVja+Y3Srk@U**@B+&F?l;|W@J)g+$@mf z%rQB(Uxv|eb759I^X9L)EsWBkRt5pA3;_@S8>FylvAOuTFs86-DcEr`gcwbpl7Exw zqvhlcB~p_+3lw3@V+FB{?vqstV<%@$WP+hVh=rL!z`MyoMaqn)CYKfYF;-7LTBOJrIr({!!sPeU-Pm

5qi{)VskS*b!d~$}Mpq>_^i;pfthLs*)g_T|i)TKaK z0dWSc06QUu3`ad5HinSR#*|DBcvH+8DQ`xdI#$5nJ0Dq?d From d74435cb61e7467a3d1fada593e084d50a421d8c Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 27 Apr 2017 19:48:19 -0700 Subject: [PATCH 33/58] Flip phase of speaker on entry/exit. Seems to work more often than not --- src/samplesrc/a2pwm/hilopwm.pla | 23 ++++++++++++++--------- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 1770f01..463a891 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -39,7 +39,7 @@ word heap // // Periods of scale in second octave // -byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 99, 93, 88, 83, 78 +byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 98, 92, 87, 82, 78 // // Key mapping to note // @@ -537,9 +537,9 @@ def main savePatch fin break - is '0' // Toggle speaker phase - ^$C030 - break + is '0' // Toggle speaker phase + ^$C030 + break wend fin fin @@ -556,6 +556,13 @@ def main until quit end // +// Get us into a standard 40 column video mode +// +call($FDED, $8D, 0, 0, 0) +call($FDED, $91, 0, 0, 0)// CTRL-Q = turn off 80 column +call($FDED, $8D, 0, 0, 0) +^$C000 = 0 // Turn off 80STORE +// // Get heap start. // macros = *freemem @@ -566,13 +573,11 @@ if not loadPatch fin recalcEnv envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) -call($FDED, $8D, 0, 0, 0) -call($FDED, $91, 0, 0, 0)// CTRL-Q = turn off 80 column -call($FDED, $8D, 0, 0, 0) -^$C000 = 0 // Turn off 80STORE grmode showMainPanel -main +^$C030 // Flip phase of speaker. This seems to help more often than not +main // Main program +^$C030 // Flip it back if modPatch if query("SAVE PATCH (Y/N)?") savePatch diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index b7166d86b42610659b0fb149c0b58e75fdb51a96..504a20fc618e753d9c1252b7ce490aba3d298599 100755 GIT binary patch delta 109 zcmZp8z|ru4V?#QNK#C&6Y$XF>28PEB3LwVja+Y3SMzhVVK_UVyNipF;n`M(ygeIRV z(VW~^;wc(3!O$SY!puO&;6Q>wh?p&yG5KGKp+K{+^f OvH%lTQ`xdI#$5o|At&nq From 26dcd43c2eb3bc72d863a5935742c50ae3b98f86 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 27 Apr 2017 20:26:06 -0700 Subject: [PATCH 34/58] Make it 1.2 with the phase fix --- src/samplesrc/a2pwm/hilopwm.pla | 4 ++-- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes src/samplesrc/a2pwm/util.pla | 3 --- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 463a891..0a601a9 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -199,7 +199,7 @@ def showMainPanel showDuration showWaveform showLFO - putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.1a") + putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.2") normal putsxy(1, 0, "1-8") gotoxy(34, 0); putc('<') @@ -432,7 +432,7 @@ def main memcpy(@record.stateStart, @current, t_state) record.absStart = TRUE record.sequence = 0 - flash + normal putsxy(29, 3, "RECORDING") inverse key = 0 diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 504a20fc618e753d9c1252b7ce490aba3d298599..9ded1d20497f1e2c39ea2803698f9b59b17f4025 100755 GIT binary patch delta 1403 zcmZ8hO>7%Q6rNez+oVoh2U&5b9cAORn`E+HkK_JAi4t(qM!4x>CQ^cWFx6)3G;ZqH zCU8Nn5Pug6$$(Hmh)R_Z5fTDf0+kCOIP`+lQwxZo1S-LW^hh8Q=FNB$T6}o>eeb>b z-p}m%@_N(d^`=kGdxO*6=-t@<5JJBqO@P|7-q%j!ftoM-TRT!3 z@g`5sgmEh$pGgD0G7|;-(TwfCk)#fC6h~z@_!qLV#D2e;R#*WC;eR(8X^B1m*2 z+=!DNWO_7B6BPloP5w^4vr1AFL0^my?5wYSnAID+1O#q zRt{0tcZg5D-d!D(IdGm}SWq&4OfDz}3j)^(wvnJjZ;&BLJfbdy;*zN@8xTyExCQc{ z1~*|UC*o2}7dSrTHbaRY#%LSSp48IX7{7bLf8L#d1mOCF_Ndejx-2VM$Ys-#wYzLm zvJRJx3kF@td7%l`3X9x_Oz)}DjKw1S>A3`s@TIvfu%FHuV1J$?V4Dk3C6eTHsRzj8 zg#%!Vg#*I%{!$Fc^@0ej75as%ZMhFf@}i9AmJb4X{-Q1-A20U;`K}SUz1#_;ZGH{z z_wM}32jTUy!blIAwyNaduA)1y9Y1r4M2Zhl%ZIFuI<-}zrZZ`5`-nEwjM!=Z=A|ES z3!g7`fYK|)o?ZNHaTq+l1$K|N@;~j;0>MT8-hvepH{1z}Z_bWBb|#x1pEwB%!KLFN zSibcDVhMPQhL2MAGCWN_QR-;fPKo~wEd!sw$xEdP80YI!1mEIoB@OI9r6=$Tx5_cx z$IIm&uy2Evjr!oTVq^UKa{qn2s}jbm{AlH^mid&F74_tSs5l@iAE5^QDo2_Bkp{?* zn0##|tZ%18AFGfi?iHFvXRijYpBh=&M6cfb^TmzTFJJm)b%2jQ^EnSH{udTMSj1oa E3lM9L*#H0l delta 1441 zcmY*YUrbw77(eIswqpTHhe#p(S!v4!j<>g`r6OcYS6sV|tg!^)6Y}zAixBg?3u3$rpLxy1FTT^ux zj>afyw9y1nYE+`YlwC2(?nT*3w4hiD8B2-2q@H~Nb)BS}ct|&5N}T5Y)=A({wiS`x zG8ZHo*+n!6tNPB4Qz6nyHQgIe$jX1N|(lT8Lnf6fl;pL<|zus7pq>D$)Oyo1gFS<-8v!c=|ML0Y1|V<8JyGnA;rWhl-Lz=ti|KApr}yl%QRBy_w>$3Z># zQ3g6Q^C`-%B`Aw0C~+gBoxk`&>rCt=Dfv$n<_AS$kpU@45CnnHezq2+M5}qp8k4BW zLB}O(cF?du5BCU!%nxT!j|}xlCTl`pex?}3F@B}E7wk7h9qhd#;s2azQy@u~!aQ|0 zEZotmoX%aEN!$ z9d3aeWBQTiGc1oXk=xYU9^NFLo+bEoK0DijPw>mLKVm<>ns0_xZ{$N&|7Jb~k*z$# zC;72CKiH``v8ps@Hg14U?Qq(=M>7YHji!f34uhC~%?%EKm}UcFgP`frrztDKf1sb5 z+nDT0b|Rzpx#Pnu&@&bt={>;Q3Gv Date: Thu, 27 Apr 2017 20:52:35 -0700 Subject: [PATCH 35/58] Add note duration section --- src/samplesrc/a2pwm/readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/readme.md b/src/samplesrc/a2pwm/readme.md index 68d9910..c7b5960 100644 --- a/src/samplesrc/a2pwm/readme.md +++ b/src/samplesrc/a2pwm/readme.md @@ -22,7 +22,9 @@ The Apple II keyboard is mapped to a one octave piano keyboard, from Bn-1 to Cn+ I A#n K Bn L Cn+1 - + +The duration of the note is in increments of 0.0255 seconds (the PWM loop is 100 cycles and runs 255 times at ~1.022 MHz). The maximum note length is slight longer than 1 second. + ## Command keys KEY COMMAND -------------- -------------------- From fce84e5c9e680f7129db81b535f5aac88754b96d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 27 Apr 2017 21:23:08 -0700 Subject: [PATCH 36/58] Add speaker phase information --- src/samplesrc/a2pwm/readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/samplesrc/a2pwm/readme.md b/src/samplesrc/a2pwm/readme.md index c7b5960..412576f 100644 --- a/src/samplesrc/a2pwm/readme.md +++ b/src/samplesrc/a2pwm/readme.md @@ -41,7 +41,11 @@ The duration of the note is in increments of 0.0255 seconds (the PWM loop is 100 / SAVE ABS MACRO ? SAVE REL MACRO P PERSISTANT STATE + 0 TOGGLE SPEAKER PHASE Command keys and note keys can be interspersed together. ### Recording Macros One of the most powerful features of the Oscillation Overthruster is macro recording. There are seven macros that can be assigned to the lower row of keys, Z ... M. To record one of the macros, type the key along with the CONTROL key to begin recording. The RECORDING text will show up to the right of the text panel during recording. When recording, other macros can be called, allowing nested calls. However, recursive macros cannot be made, i.e. macro Z calling macro X calling macro Z. If, during recording, you want to cancel the macro, press ESCape. Their are two ways to save the macro: absolute and relative. An absolute macro will retain the state settings at the time the macro is recorded. Octave, duration, and LFO settings are restored before the macro is played, then restored when it is done. A relative macro will use the current settings when playing back. To record a rest, the spacebar will insert a pause for the length of the current duration. You can make the current macros persistent by pressing 'P' to write the macros and current settings to disk for the next time. + +## A note about speaker phase +I discovered that the Apple ][ and Apple //e are affected by the initial phase of the speaker when implementing volume control with PWM. Interestingly, the Apple //c and emulators aren't impacted by the speaker phase. The hack was to add a command to flip the speaker phase (the '0' key). If you notice diminished volume when you run Oscillation Overthruster, press '0' to see if it doesn't clear up the problem. I hope to find a solid solution to this someday, but this is the fix for now. From feecad3529d8972054b4d3f7b5e0296c9db0a23d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 27 Apr 2017 21:39:36 -0700 Subject: [PATCH 37/58] Remove initial phise toggle --- src/samplesrc/a2pwm/hilopwm.pla | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 0a601a9..7db7630 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -575,9 +575,7 @@ recalcEnv envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) grmode showMainPanel -^$C030 // Flip phase of speaker. This seems to help more often than not main // Main program -^$C030 // Flip it back if modPatch if query("SAVE PATCH (Y/N)?") savePatch From 0c488bd060aacc8900de1a27ff7ed613eae545c6 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 27 Apr 2017 21:40:44 -0700 Subject: [PATCH 38/58] Remove inital phase toggle --- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 9ded1d20497f1e2c39ea2803698f9b59b17f4025..0ed1df32052a84f01ec27d4e6aea2ab8e86b54cb 100755 GIT binary patch delta 34 pcmZp8z|ru4V?z!Lw}vPK!(#@8*-9Fs&E+iZ Date: Thu, 27 Apr 2017 21:42:57 -0700 Subject: [PATCH 39/58] Remove initial phase toggle --- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 0ed1df32052a84f01ec27d4e6aea2ab8e86b54cb..f5df55e810fea49f28a4b1a217884916b6008de7 100755 GIT binary patch delta 76 zcmZp8z|ru4V?#O%zrP~GY$YvG28PEB3P8r@GL}AHM#asnL9dmVL%3}x|1B{TuydUG gj-lhi_m+n%_qRS;sW{oL^w4AhCa$KkWo3-J00IOZPXGV_ delta 90 zcmZp8z|ru4V?#O%f21PAY$Xj*28PEB3P8r@GL}AHM(xe4L9dkrbqo$97=&=!8h{xY rj(U^t&J>@_S1Kmp;W+ahL&t^hEe}`jZ+)~ Date: Thu, 27 Apr 2017 22:31:59 -0700 Subject: [PATCH 40/58] Revert to previous frequencies --- src/samplesrc/a2pwm/hilopwm.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 7db7630..d1afae1 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -39,7 +39,7 @@ word heap // // Periods of scale in second octave // -byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 98, 92, 87, 82, 78 +byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 99, 93, 88, 83, 78 // // Key mapping to note // From 0152b5554ca0027f98f61814c5885f85bf8ad067 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 27 Apr 2017 22:33:36 -0700 Subject: [PATCH 41/58] Revert to previous frequencies --- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index f5df55e810fea49f28a4b1a217884916b6008de7..452e539ae11dff79a0d129f4cff5a2dbb604aea0 100755 GIT binary patch delta 39 vcmZp8z|ru4V?z!Lx1tyW!(#@8*-DCHo6A`i#ZH!Nk8iF>+Fp^w*l`vB3(yWN delta 40 wcmZp8z|ru4V?z!Lx0Waa!(#@8*-BcXo6A`i#j+&Dga Date: Fri, 28 Apr 2017 12:08:32 -0700 Subject: [PATCH 42/58] Hand tune each not as best as possible --- src/samplesrc/a2pwm/hilopwm.pla | 16 ++++++++++------ src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index d1afae1..0ce230d 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -39,7 +39,11 @@ word heap // // Periods of scale in second octave // -byte scale[] = 166, 156, 148, 139, 132, 124, 117, 111, 104, 99, 93, 88, 83, 78 +byte scale0[] = 163, 154, 146, 137, 130, 122, 116, 109, 103, 97, 92, 87, 82, 77 +byte scale1[] = 82, 77, 73, 69, 65, 61, 58, 55, 52, 49, 46, 43, 41, 39 +byte scale2[] = 41, 39, 37, 34, 33, 31, 29, 27, 26, 24, 23, 22, 21, 19 +byte scale3[] = 21, 19, 18, 17, 16, 15, 14, 14, 13, 12, 11, 11, 10, 10 +word scale[] = @scale0, @scale1, @scale2, @scale3 // // Key mapping to note // @@ -199,7 +203,7 @@ def showMainPanel showDuration showWaveform showLFO - putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.2") + putsxy(5, 0, "OSCILLATION OVERTHRUSTER 1.3") normal putsxy(1, 0, "1-8") gotoxy(34, 0); putc('<') @@ -306,9 +310,9 @@ def playback(idx) for i = 0 to 13 if keytone[i] == key if current.LFO == 0 - hilopwm(scale[i] >> current.octave, 0, 0) + hilopwm(scale.[current.octave, i], 0, 0) else - hilopwm(scale[i] >> current.octave, current.LFO, current.idxLFO) + hilopwm(scale.[current.octave, i], current.LFO, current.idxLFO) fin break fin @@ -404,9 +408,9 @@ def main for i = 0 to 13 if keytone[i] == key if current.LFO == 0 - hilopwm(scale[i] >> current.octave, 0, 0) + hilopwm(scale.[current.octave, i], 0, 0) else - hilopwm(scale[i] >> current.octave, current.LFO, current.idxLFO) + hilopwm(scale.[current.octave, i], current.LFO, current.idxLFO) fin break fin diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index 452e539ae11dff79a0d129f4cff5a2dbb604aea0..fbc2625b80d1c00266e4fae38beb5c04398ec811 100755 GIT binary patch delta 2510 zcmaJ@du&rx7(e&4>joWV8?f=(xa(NEo!y?DZbc`uuD~`J-obSqq>zP_rQ9{Mz+e>{ z5;I~nz8JC{U#N*7jKDv{2qZpYM2sdzjhJXcVl;pn_(w!zbPRNU=kzil8k?;5_dV|S z{=RPa`GVc&3*PK?7d=slUh@|eBJ=~&B{=bjd#F=ecOtLrk`Et?ozSpfiyeApR#8?+11(6wzPTi-H|Y@s}0r$tNoP=%ID3UT~<14#;h47#YNM7zG;PC@6@S9 zw1OIRF%=a(>pdUSQ(q5#A|CCTTX%u(y-4@`KvP3M(j(`OT{u8rIQ{(DngoK+snaLV z4qc;r#_8o#r-#N)oayP(YDX!-II%(Z>2a(Xn@%Tegvsuel0l~N8LV4^d;p?3IS0cd zo*dNr#kpj|qERZfjQ9;{oR3ne8uz$tWMi&}neFENOljP6-O*sYMYL=t8#6SCDtd^X zz_vyz6CBqw>*53hD|%SHQ9t>H5u1d(C9GUPoXIiUF)7vKZfu}28zW#s9OA2IO0`k( z{pPZHxe(*tJQ)-OG!9`&~i-{G<#U| z+hzF@(9~hE*VgkC7Vke>nG>J0LsgDgl_Z|05iNslw9`dCtik-|t2MpL2d~wuh&2@0 zLJc&ZKi-f*No4xrtM9sD_%xF5;b$6H5(Tap&;bSc5y?QyZoSH5jSMW1kBA3xpTf6U z3*2Gt@-1tZ2PKx~P<8;C;Fxr2yfn=CK$wx4HcAj&;3g10?*!&t#xcv_Bqr-)(m$Eb zzX82U5+oiHM4U9R)HQ?X?dCj0rYM=81V}y!0NZU$OgI`+jCrqoSIUD@N&=3YR3Ylp zbzOP{EXN1rd{~WN+%0>J`hGL|emDC5FnD((Lm*C#8~jOtJv(tOCE7_=bpxKUX=}sCrlkh0vhF;ZT#R zuwPY}EP=IVB#9<)Yv&>6}3;DP9s%#sU(DqRJ6W5%EG2#Y^=E z^j5unP+y_1)K}^E>E>i0J{SY&FKJUQiX5s-Q8OKCy`oATYOSJXJ5-0HZl(>fz*%5q zI->5CZKfr?K)q?OS$)JK`~0{wEMDDLAs_GUtCNq*`)ajL@%KaXCBcTPfQY3RN@CY= zm3+KD><8ZQv?4AI*GOLRh204D z%Y|q+r^v}Kgot=l9O$224J&FbLnIUhi}{F5jV@BFqqXKVeUqAXQWKOgVpi4P3=*!% z|G#XtZZY0JZ_r@ogD&SbL7Y&aCMSRRHA`y$nLkMWoj)-Doj;gsH9yDF?qvRsUC19p z{v+G{+GcTT`+^|!1vWeT7j)PglDk35VF9LewJl%M)!MOog|ipp`u0c@%!O5g_$C;S z9d|SSHart|G3&ZUildc?dhcJ`!S$N;^{Z=Jcqk(8iEhGuPl(aUkuEVLjkQ;@>{JgSMo(S zgIS1(6`hV!161bttuQjp^}P(vrg`WFk_XTD`7bi0mVz>ghi}6_+ev7JYDYVZC7J_@4? delta 2461 zcmaJ@Yiv|S6rP!V^s!}WkrZ&-a(994GQB%H+fu9xtSy$8F1prfQV79KbG#W+qSYnG2G-!z!OURwp0s_Z#)&Ne+^7|W`3v4qe&8{oTi6}5-+U57y$R=W( zbK5J@TwB~a;aYGpOYXX#Ze7hRRM$<79I-JC=fnu(*>5K~co}zYB&Kedty83!mDC{! zHm%FH>rw^i@)8qWwh00ueS_TnmEi&yze` zjcl*&w~-hH3q=v2 z`L#}#Z;LN-jWkkSKG(r+4?R1>!RBqZ51dQr5Ew;QFcZ~?j>aOgP$mLjJrkxG#I(dO zh8nqrqT?o=<&dJN1Zeg2RS|6B;DLTb{YZS%sOTBqqStvlJ?-uEfTEQ<)ZYfRab0?_ z_?~momgIDCwcxalNxI? zAwOb(syw`JehWZGgUY>yEPPD^GB5Qo;(`FQMj^!j1r-e{B!AtPxK-8UYk=pn zNz45dv-0@VqwDp(#_U=>#oA^r4ld&&woG=t5FTjMHgKO}Ks*_5(TGPh;&dfUKc`WL zNo&UAq(S4F^SfMw;&g}$;2yj|X&G4=*UqAfj;GyZI1RvCRka!S8tul~0b`x9-nhfK z)5uIE5`?yZdeb#JM5W7hXl|~{ZPHw|%XMmQzRPV;93-P!Mdbq9gVWiFdDpMWWK|Tv zpVhC@k9=e(LPAM-XsAvd?+-Po6PBb)X*XFFm*zz8CDMi#UU%GK2=9rKSDjChGsiR17KY{|yMa zX-9l+ib2=n)EpEv-@HP5py@?HzOrNGQj*{{$z@ikrC<|iT-XdC%a5D+Urdt!6+XY2 zq(8;vecP*N!+cQO>jlFg$+eu9WAdhfb*Lg*$1Fd|S-#fHay37wHB*hEm0AexR0Gjq zoU-#~%BIIG>qFVolic#tS?!sf81?$8zoiDenp0i_$nuMaQe2siX;XiDrX5>8YWUJ+ zNNkiJ?EG{NymM@Arc8}W1!OELQgZ9|c~M9@yBg7W8ZMV0TAprJ78JKTrom~`24xCX z1o7;We>gxAEBQY>FqLdqXyETeMtIzH2I&KYEiNboK*2YH0>b}*;>!LD3OH-ed_k1g zDNtOm018o{$j^2exJmxFYhgW94wgaxRp^00T(vB%g&8U9SabW`9qk+LTIY_AO!h5n zfzHX!K_UTD-+BudPs7QU^XvqsRp~HdfqObP2qU&Bao5t@#6*)?K}H6C5}16oFIfkH z(4zsSg0(Rx2rOCW5h3|gUx-|2mSu&7>Y#-zJ}4h6L~u;LR#+5`E#ujfh&H$d38Yu* zf|@ wIu_{E+5m{rmcy0rrrQpVqi09{d~)pAhfjTbEG&B-epyzMHq)$ From 734de4a5e3a29203501924b62b7cd9d857c55148 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Fri, 28 Apr 2017 17:19:26 -0700 Subject: [PATCH 43/58] ReEewrite sequence playback to be fast enough to not pause during state changes Hand edit a few tone values to sound better --- src/samplesrc/a2pwm/hilopwm.pla | 282 +++++++++++++++++--------------- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 2 files changed, 150 insertions(+), 132 deletions(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index 0ce230d..d88b844 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -4,6 +4,40 @@ const iobuffer = $1C00 const NMACROS = 7 const FALSE = 0 const TRUE = !FALSE +// +// Sequence values +// +const SEQ_MACRO = 0 +const SEQ_NOTE = 7 +const SEQ_LFO = 21 +const SEQ_LFO_INC = 29 +const SEQ_LFO_DEC = 30 +const SEQ_OCT_INC = 31 +const SEQ_OCT_DEC = 32 +const SEQ_DUR_INC = 33 +const SEQ_DUR_DEC = 34 +const SEQ_REST = 35 +// +// Predefine replay functions +// +predef playback, replaynote, replayrest +predef replaylfo, replaylfoinc, replaylfodec +predef replayoctinc, replayoctdec, replaydurinc, replaydurdec +// +// Replay function pointers +// +word replay[] = @playback, @playback, @playback, @playback, @playback, @playback +word = @playback +word = @replaynote, @replaynote, @replaynote, @replaynote, @replaynote, @replaynote +word = @replaynote, @replaynote, @replaynote, @replaynote, @replaynote, @replaynote +word = @replaynote, @replaynote +word = @replaylfo, @replaylfo, @replaylfo, @replaylfo, @replaylfo, @replaylfo +word = @replaylfo, @replaylfo +word = @replaylfoinc, @replaylfodec +word = @replayoctinc, @replayoctdec +word = @replaydurinc, @replaydurdec +word = @replayrest + // // Patch state // @@ -32,6 +66,7 @@ word macros // Pointer to macros byte record[t_macro] // Recording buffer word recording = FALSE // Recording key/flag byte playing = 0 // Keep track of active macros +byte recalc = FALSE // Recalc envelope flag // // System variables. // @@ -260,23 +295,15 @@ def recalcEnv current:rateAtk = $0FFF/current.durAtk current:rateDcy = 0 current:rateRel = $0FFF/current.durRel + recalc = FALSE + return envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) end // -// Rest -// -def restnote - byte d - - for d = duration downto 1 - call($FCA8, $6A, 0, 0, 0) - next -end -// -// playback a sequence +// Playback a sequence // def playback(idx) word macro - byte seq, key, i + byte seq, i byte save[t_state] // @@ -298,91 +325,14 @@ def playback(idx) memcpy(@current, macro + stateStart, t_state) duration = current.durAtk + current.durDcy + current.durSus + current.durRel envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) + recalc = FALSE fin // // Run throught the sequence // - for seq = 1 to macro->sequence - key = macro->sequence[seq] - // - // Check for tone keys - // - for i = 0 to 13 - if keytone[i] == key - if current.LFO == 0 - hilopwm(scale.[current.octave, i], 0, 0) - else - hilopwm(scale.[current.octave, i], current.LFO, current.idxLFO) - fin - break - fin - next - // - // Check for macro keys - // - if i > 13 - for i = 0 to 6 - if keymacro[i] == key - playback(i) - break - fin - next - if i > 6 - when key - is ' ' - restnote - break - is $15 // -> - if current.octave < 3 - current.octave++ - fin - break - is $08 // <- - if current.octave > 0 - current.octave-- - fin - break - is '1' - is '2' - is '3' - is '4' - is '5' - is '6' - is '7' - is '8' - current.idxLFO = key - '1' - break - is '<' - is ',' - if current.LFO > 0 - current.LFO-- - fin - break - is '>' - is '.' - if current.LFO < 32 - current.LFO++ - fin - break - is '+' - is $0B // UP - if duration < 40 - duration++ - fin - recalcEnv - envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) - break - is '-' - is $0A // DOWN - if duration > 1 - duration-- - fin - recalcEnv - envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) - break - wend - fin - fin + for i = 1 to macro->sequence + seq = macro->sequence[i] + (replay[seq])(seq) next // // Restore state @@ -391,17 +341,87 @@ def playback(idx) duration = current.durAtk + current.durDcy + current.durSus + current.durRel envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) playing = playing & ~(1 << idx) + return recalcEnv +end +// +// Replay rest +// +def replayrest(idx) + byte d + + for d = duration downto 1 + call($FCA8, $6A, 0, 0, 0) + next +end +// +// Replay note +// +def replaynote(idx) + if recalc + recalcEnv + fin + if current.LFO == 0 + hilopwm(scale.[current.octave, idx - SEQ_NOTE], 0, 0) + else + hilopwm(scale.[current.octave, idx - SEQ_NOTE], current.LFO, current.idxLFO) + fin +end +// +// Replay duration +// +def replaydurinc(idx) + if duration < 40 + duration++ + recalc = TRUE; + fin +end +def replaydurdec(idx) + if duration > 1 + duration-- + recalc = TRUE; + fin +end +// +// Replay octave +// +def replayoctinc(idx) + if current.octave < 3 + current.octave++ + fin +end +def replayoctdec(idx) + if current.octave > 0 + current.octave-- + fin +end +// +// Replay LFO +// +def replaylfoinc(idx) + if current.LFO > 0 + current.LFO-- + fin +end +def replaylfodec(idx) + if current.LFO < 32 + current.LFO++ + fin +end +def replaylfo(idx) + current.idxLFO = idx - SEQ_LFO end // // Main loop // def main byte quit, key, i - + word seq + quit = FALSE repeat if keypressed key = toupper(getc) + seq = -1 // // Check for tone keys // @@ -412,6 +432,7 @@ def main else hilopwm(scale.[current.octave, i], current.LFO, current.idxLFO) fin + seq = SEQ_NOTE + i break fin next @@ -422,6 +443,7 @@ def main for i = 0 to 6 if keymacro[i] == key playback(i) + seq = SEQ_MACRO + i break fin next @@ -439,7 +461,6 @@ def main normal putsxy(29, 3, "RECORDING") inverse - key = 0 break fin next @@ -473,21 +494,36 @@ def main putsxy(29, 3, " ") fin break + is $0B // UP + if duration < 40 + duration++ + recalcEnv + showDuration + fin + seq = SEQ_DUR_INC + break + is '-' + is $0A // DOWN + if duration > 1 + duration-- + recalcEnv + showDuration + fin + seq = SEQ_DUR_DEC + break is $15 // -> if current.octave < 3 current.octave++ showOctave - else - key = 0 fin + seq = SEQ_OCT_INC break is $08 // <- if current.octave > 0 current.octave-- showOctave - else - key = 0 fin + seq = SEQ_OCT_DEC break is '1' is '2' @@ -499,13 +535,7 @@ def main is '8' current.idxLFO = key - '1' showWaveform - break - is '<' - is ',' - if current.LFO > 0 - current.LFO-- - fin - showLFO + seq = SEQ_LFO + current.idxLFO break is '>' is '.' @@ -513,45 +543,33 @@ def main current.LFO++ fin showLFO + seq = SEQ_LFO_INC + break + is '<' + is ',' + if current.LFO > 0 + current.LFO-- + fin + showLFO + seq = SEQ_LFO_DEC break is '+' - is $0B // UP - if duration < 40 - duration++ - recalcEnv - envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) - showDuration - else - key = 0 - fin - break - is '-' - is $0A // DOWN - if duration > 1 - duration-- - recalcEnv - envelope(current.durAtk, current.durDcy, current.durSus, current.durRel, current:rateAtk, current:rateDcy, current:rateRel) - showDuration - else - key = 0 - fin - break is 'P' if modPatch savePatch fin break - is '0' // Toggle speaker phase - ^$C030 - break + is '0' // Toggle speaker phase + ^$C030 + break wend fin fin fin - if recording and key + if recording and seq >= 0 if record.sequence < 255 record.sequence++ - record.sequence[record.sequence] = key + record.sequence[record.sequence] = seq else beep fin diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index fbc2625b80d1c00266e4fae38beb5c04398ec811..b1388400f094ccf6ce5261acaf936bcea2726a8c 100755 GIT binary patch delta 3193 zcmb6bTWlOx_1wGT^?Pk6j`Of%#&)`PuXkqe+Kyv8+s*o!q#4?ceVsav)vnBRys<(k z;J7Ozv=LA>g*wp$g_ftI=<7eCuXg8t}8W@#C9|1JRcUqaUtqEcQpQ{cHLp zA)D?|dwaj_obtk!`vqa_-{`->|`{0tW-_#Cw0F z={J}@V$}mHRlH^vX2mRwWG#}<`x25(g(Gz(zg2Qs*ypnrFax@-OOFW4wnD!6qiV_t zP4)oH_8GHrV>V%k*E%^MJ2PO2n+Q(NQ!gmMsJxh5a(2&*bcJEqM6-brEHvUo1t@9A zC{P26`iMu}CZ2jT&okXd=8%!;F*3cz_7GGpC}h^$i)U-w*G!o-S<1|sN#_Viiz1su}Oi&nZ^Pp_49zRO2nFpiIDEFNbWx_M|)*i#xX-l zgOvptG0Tj?N0sauH9uP=6*mrYQHy^+=yE5%*_7*4GN{i8COu~KsH8Wmq_en~;+%y& zB%zRi7X~vF7WA=pi76K+yHzw;U6aNQWh^XVBjE?bSvlUSre7b^hxC!0epElEKdzt9 ztwJCn>uCP5mc3ff@j9eQsGq^!Gs{&IyHf*J&7c79; z`k4B-&o4F8D>3&wOO5h)XQ^EtA1*yguDJYMgGBgpi#*1?W5GMVx7>^px6UcnUzXdX zM9qpi4zDO;dgT#Ge9=4JUTH=7e}47={@;7PG3U*aj1W77m6T+=4aj0+sm{svN&s6; z!!FaZJw_y7g;>c#p8*STh4mtqK$TNc?4cd0mgY{988;bmU|+3;b2GVx)B(+Cv` zvWsYXP77~FY^`y+D`#unr+Dg5d5(VCg8#RZt$XaK#e0Ys`_%Xa2xjdZ2Hm#Ts3Ug@B&~fAUN&)f8mAp##Trec4(^du{e$#vJ7&uk zR;z8qs*+P)fjPm6#>*ExA(sq!+|UEu93^sI10z-`AW)G_8U-~3hdgp~Z>skibRpNGmJ>oqFP2YZ^){2K-HHDFVbyWPj} z^fj;zP$M{G&C%I0Q@755r#Om=Zxkkd%X~N3Ur(6!$ZZ%u&CVN<}bJm23?<34e;2qIlnJcEDQQ2Ux1lfe>{9&!y17 zRgMp`wSHF(QsmBm*`mKJB)q&0F3@2Eo?~=+VbJgv=L!66Mi-uvYZUxnYWRy*{Iyf{ zf$SN%V?JR!7aB@@5a*e7H*#SQoA2^(rXDS9JeYd5`a11@WfLyl{P)-Xy!wk5-dlbD X1-hDa&tF(^tLYcMGXMHK`RV@vCPF`C delta 3188 zcmb7GU2GKB6+Ux!Jzlf++A+p}F=qXfwYj-_J!@>@x@K(>n*?c0C*;!Dh(;TC7;nuw zwd$3-^+PwRf=DEciltCpA7;=0Idji<&Yc&ogkHE3`sq}#?szNwxGhu-@F7GcapBv+#WC{C-V6G{ ze@4ji@CA*uY3{^if2fYPaK;C?+j3%}@^}2=dyBv4?srdYWmoyBYy9MgJiYjLe*Vhx z)ieBumws@$D+Tzwcv(P9e(}drNtF~A^G*EH0_-GeS3R&qj4k}iPB23(Qx;? zyp`bJ_{({1)_wYDPv1Fy7?o`No{S>SacMfP2OMySh$ajtC}s_1@uj=Ig&~IAw~x}V zWw{M4lQfzljz(Kkf^-|!wSs|Bq6y{EUGiYVB~lC}R0^Uod&TiXO7rm`VX)#5K%qG2 z?sYczdbMFSH13dD)+OzopsZ3kgezo~Sm7P4Q&Kuo?n$S$83opjf?+kHxuZKE>U;1_ zkRqbq{e#oe{tupeo!eDjUX5y5;y^Y)-|ZqosnV}=*O=NC`eT=_1a5q)Ehsha(^GNJ z8%>mZh3`Hepub*ocVC-&JipqlEHsGCa0bod#hxtKV7B37`YvM;jaKU7H$8?8v73z6 zc%(Ql1@PFKs~Fy8U#YbApz4Lv*}OR^ruW5*<}E# z(|4FSf#l>o@rnYhs#p_bfbQr&1l10)fuv}lIjezqKacUTG+PVWKs9WAk3lt6w3MNu zBn>F(!=ALv+H8nI%VMXt{ff9f^FVfUTsj^}-6s$mxr@qX2XHq`|>h#SJ7 zF^@?qCg9aTieFfuo0Vp8+w zQYSKdo>!U=mbT~Rdo?N8%7%wRxtk1fh!xfS+-*r9dV&a?VD1)Ug<9l73m-FB_(XBH zk^7W^+J~A13gTEBsD}u9;~t&HF~Ch{SpUMEs=(HurE56V9B67VaZCgzZv5`TZ$V7 zTNghWFr?{KWvY*uBbr??K%>bj5P4MfX>?O^6G+?#_L)_ZsLri0Yr956$p*>7h$oIn zvF_gb(O|v?>QX;7aB z`iQR&CwsifS7l^)H6Ef!4y>~*^8OOD9s?Tpy*DKLl((j`XL#fby^GFRGy%hE|IENv zc2)i#eaw41vX7r+{2pf*Iyl1ODR2#vnxc{e}~4xVCP?QS)HKQTSlP3C&~2 z-z73|spEcN>^Ld!I9iODXUTM!N6lx!^T3@RJIZa}V+4044K>-MaUslOpRp3kaeLbc_O zd3-PPzr$yVUurw;8G(XNT^13QOAyjQOKsEL=fwD~}z zLkQeFU}X|<-N|8<=u!Xf$E38-pp)2r`6VFdQWhZJWNzIuUXtM7Q3QWo5&Qx-Fus+1 zH~b6>C0qP4PzE>#HLT2H6enUd&*W`jt(FhNmj50GaTrbhQa%t{9~cN_^Rx1y7%UD& zToPX}6q&V~U0zLo@yE)?!;6FCq2m0{@hA(^0n|#?LVAwNKKyl;`_WuuKFn>c!)%9i zI8F=u%tlF6BUobLI8um$SqqJ)47`lZ*Y2t5U^nj5MSlZJ`g9pxlEWpKrDSs9E-QV` zk%fp{#o&M3;Wx23)3-~3LIP;r72ywg5nW Date: Sat, 29 Apr 2017 07:29:21 -0700 Subject: [PATCH 44/58] Fix oops of moving increase duration code --- src/samplesrc/a2pwm/hilopwm.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samplesrc/a2pwm/hilopwm.pla b/src/samplesrc/a2pwm/hilopwm.pla index d88b844..623b008 100755 --- a/src/samplesrc/a2pwm/hilopwm.pla +++ b/src/samplesrc/a2pwm/hilopwm.pla @@ -494,6 +494,7 @@ def main putsxy(29, 3, " ") fin break + is '+' is $0B // UP if duration < 40 duration++ @@ -553,7 +554,6 @@ def main showLFO seq = SEQ_LFO_DEC break - is '+' is 'P' if modPatch savePatch From 2407d1bb7e907196e6bfbd0dd2bc58e9a80beb94 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Sat, 29 Apr 2017 07:30:16 -0700 Subject: [PATCH 45/58] Fix oops of moving increase duration code --- src/samplesrc/a2pwm/lfo.po | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/samplesrc/a2pwm/lfo.po b/src/samplesrc/a2pwm/lfo.po index b1388400f094ccf6ce5261acaf936bcea2726a8c..1ef9ec7af7021fccefb9b3ecbc8dbd66a6e4cbee 100755 GIT binary patch delta 92 zcmZp8z|ru4V?!1T?_4Drb_RyW3<@B|=5iLpJa%n6R)zp}hRMr|lo*XBpDNO3WSji0 wNS^W8WU*p7rsE8gKTfxvTv#m5SUkD2Se?;(^2TB{MwR9V#oHegGb-!>07vH^djJ3c delta 92 zcmZp8z|ru4V?!1T?;IszK?a7$3<@B|=5iLpyvZAi6dA21UnnY%0KrKh761SM From f6315d1bd17234102ffe6e73b3bbb41f703367bd Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 30 Apr 2017 08:25:05 -0700 Subject: [PATCH 46/58] Prepare for extended ops --- src/vmsrc/plvmzp.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vmsrc/plvmzp.inc b/src/vmsrc/plvmzp.inc index 82140ec..2e6aebb 100644 --- a/src/vmsrc/plvmzp.inc +++ b/src/vmsrc/plvmzp.inc @@ -10,6 +10,9 @@ DST = SRC+2 DSTL = DST DSTH = DST+1 ESTKSZ = $20 +XSTK = $A0 +XSTKL = XSTK +XSTKH = XSTK+ESTKSZ/2 ESTK = $C0 ESTKL = ESTK ESTKH = ESTK+ESTKSZ/2 From acbdde78794929e9b13e4e5a5fc709d33b6acfee Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 20 May 2017 11:52:52 -0700 Subject: [PATCH 47/58] Add Apple II GS support to SPI gameport interface --- SDFAT.PO | Bin 143360 -> 143360 bytes src/libsrc/spiport.pla | 251 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 233 insertions(+), 18 deletions(-) diff --git a/SDFAT.PO b/SDFAT.PO index 9996f265b44d4abe4a0f56f4f38ee0c365f86038..8118fbb517ea1cba85e920285f32a679cedfc283 100755 GIT binary patch delta 1077 zcmcJNQAkr!7{|YR@0@2#<*wrrF|ce7yGksQ^{Nt)um`E3+nlswN%+vy2p!QB5qeo< zBO;PApMnau*6^VRujxXi;^xXw2!vwPOB6^!VD>*wiy|b5F8t2@pO5c+-~T)J_Aj&k zWtMzjRPG}a`HSd5jk=BK4XHw;SBuKbQgyndWaUDMK$5-{z)f7sjA@bW12B$abZjhxirQ`DP^`^+WcA=d6edi4{(_` z!(;JRm|TF#`3;jkS?aN=josvK48L`I$Lc~yXri!J<8R# za&q2S58ho5J`_Q3o>NOuws4Z|zyTtl4~&2bfQ*4sg@$)4G|&h<(Cvyed=i{dq=B=i z5R8Ef;3BvT#=sqr0vYfayau0ecolD}2}OYlIM@LyK{coWwV)2vgMDDXDKUP({-}lL zjM?ezlSx0b3z^G4JH#A9&1a|DSwyH;^Rq9qk6s>TeTDeswAhSnZv1SbAahwS%k#nJ L^mubxx*h!vn6ije delta 551 zcmZp8z|ru4W5Y{Uk#GiP22*AR0YzqB28PEB0wBibzpQ+0jP{#(c)l!Tiiq6I$n=j< z*pI3176U_-AP0ko(BZR3F5e7hm@K`nnK5Cq@A`NkX}(FpQ%ivH#LS2Ty$%N!Fi^yv zykL{GRYC+4qt1#yX$(LR!oUy}!NRD;n8T!%Vxh>O#l@7y5F#j0!koga_20>djlm#= zIVy!Iq)N~r;LhaW&8qdCf-w;+Oj^7loq`5wOj;Z=5C)iJNMj25DgZQ*Ns9-U{8XSk zBLhPT&~iZmEeEF*1{EIxh7<{$iUPI z#BtYv#BCt{4aCwy3`{`jiEWGwjkAGx9V5fU9gK_KVpkycWSV??i*}Hpz~u`kj~qR7Fp{H65XiiI^qdPvCx~_F z=;1JqYarJ3ODC@!J#^KL<2FS6;1Lk#H;fa>AuR+}fB9$#hrLj9;@0hnTN&q9Z7$fV G%LD+?x3@R| diff --git a/src/libsrc/spiport.pla b/src/libsrc/spiport.pla index 1a6bfa5..405034f 100644 --- a/src/libsrc/spiport.pla +++ b/src/libsrc/spiport.pla @@ -8,11 +8,16 @@ const SPI_SLAVE_READY = '@' const SPI_SLAVE_ERROR = '!' const SPI_SLAVE_BUSY = $FF +word spiReadWriteByte, spiWriteBytes, spiReadBytes + asm spiInc -!SOURCE "vmsrc/plvmzp.inc" +!SOURCE "vmsrc/plvmzp.inc" +!CPU 65C02 end -export asm spiXferByte(outbyte) +asm spiXferByteStd(outbyte) + PHP ; DISABLE INTS + SEI STA $C05A ; ENABLE SLAVE LDY #0 ; ASSUME MSB IS ZERO LDA ESTKL,X ; GET ARGUMENT @@ -20,7 +25,7 @@ export asm spiXferByte(outbyte) INY ; IT'S A ONE + STA $C058,Y ; WRITE BIT 7 STA $C040 ; CLOCK - LDY #0 ; DOING THIS HERE GIVES TIME FOR OUTPUT TO BECOME STABLE - NOT REALLY NEEDEDd + LDY #0 ; DOING THIS HERE GIVES TIME FOR OUTPUT TO BECOME STABLE - NOT REALLY NEEDED ASL $C061 ; READ BIT 7 INTO CARRY ROL ; ROTATE INTO ACC BPL + ; REPEAT FOR ALL BITS @@ -74,10 +79,93 @@ export asm spiXferByte(outbyte) STA $C05B ; DISABLE SLAVE ROL STA ESTKL,X ; SAVE RETURN PARAMETER + PLP RTS end -asm spiReadBytes(buf, len) +asm spiXferByteGS(outbyte) + PHP ; DISABLE INTS + SEI + LDA $C036 ; SET 1 MHZ + PHA + AND #$7F + STA $C036 + STA $C05A ; ENABLE SLAVE + LDY #0 ; ASSUME MSB IS ZERO + LDA ESTKL,X ; GET ARGUMENT + BPL + ; CHECK MSB + INY ; IT'S A ONE ++ STA $C058,Y ; WRITE BIT 7 + STA $C05C ; CLOCK FALLING EDGE + LDY #0 ; DOING THIS HERE GIVES TIME FOR OUTPUT TO BECOME STABLE - NOT REALLY NEEDED + STA $C05D ; CLOCK RISING EDGE + ASL $C061 ; READ BIT 7 INTO CARRY + ROL ; ROTATE INTO ACC + BPL + ; REPEAT FOR ALL BITS + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + LDY #0 + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + BPL + + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + LDY #0 + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + BPL + + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + LDY #0 + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + BPL + + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + LDY #0 + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + BPL + + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + LDY #0 + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + BPL + + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + LDY #0 + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + BPL + + INY ++ STA $C058,Y + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + STA $C05B ; DISABLE SLAVE + ROL + STA ESTKL,X ; SAVE RETURN PARAMETER + PLA + STA $C036 + PLP + RTS +end +asm spiReadBytesStd(buf, len) + PHP ; DISABLE INTS + SEI LDA ESTKL+1,X STA DSTL LDA ESTKH+1,X @@ -122,10 +210,77 @@ asm spiReadBytes(buf, len) DEC ESTKH,X BNE - INX ; REMOVE AN ARGUMENT + PLP RTS end -asm spiWriteBytes(buf, len) +asm spiReadBytesGS(buf, len) + PHP ; DISABLE INTS + SEI + LDA $C036 ; SET 1 MHZ + PHA + AND #$7F + STA $C036 + LDA ESTKL+1,X + STA DSTL + LDA ESTKH+1,X + STA DSTH + LDA ESTKL,X + BEQ + + INC ESTKH,X ++ LDY #$00 +- STA $C05A ; ENABLE SLAVE + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 ; SHIFT IN ALL BITS STARTING WITH MSB + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + ROL + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + ASL $C061 + STA $C05B ; DISABLE SLAVE + ROL + STA (DST),Y ; SAVE TO BUFFER + INY + BNE + + INC DSTH ++ DEC ESTKL,X + BNE - + DEC ESTKH,X + BNE - + INX ; REMOVE AN ARGUMENT + PLA + STA $C036 + PLP + RTS +end + +asm spiWriteBytesStd(buf, len) + PHP ; DISABLE INTS + SEI LDA ESTKL+1,X STA SRCL LDA ESTKH+1,X @@ -142,49 +297,49 @@ asm spiWriteBytes(buf, len) + STA $C058,Y ; WRITE BIT 7 STA $C040 ; CLOCK LDY #0 ; DOING THIS HERE GIVES TIME FOR OUTPUT TO BECOME STABLE - ROL ; ROTATE NEXT BIT TO SEND + ASL ; ROTATE NEXT BIT TO SEND BPL + ; REPEAT FOR ALL BITS INY + STA $C058,Y STA $C040 LDY #0 - ROL + ASL BPL + INY + STA $C058,Y STA $C040 LDY #0 - ROL + ASL BPL + INY + STA $C058,Y STA $C040 LDY #0 - ROL + ASL BPL + INY + STA $C058,Y STA $C040 LDY #0 - ROL + ASL BPL + INY + STA $C058,Y STA $C040 LDY #0 - ROL + ASL BPL + INY + STA $C058,Y STA $C040 LDY #0 - ROL + ASL BPL + INY + STA $C058,Y STA $C040 STA $C05B ; DISABLE SLAVE - INC SRCL + INC SRCL BNE + INC SRCH + DEC ESTKL,X @@ -192,9 +347,59 @@ asm spiWriteBytes(buf, len) DEC ESTKH,X BNE - INX ; REMOVE AN ARGUMENT + PLP RTS end +asm spiWriteBytesGS(buf, len) + PHP ; DISABLE INTS + SEI + LDA $C036 ; SET 1 MHZ + PHA + AND #$7F + STA $C036 + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDA ESTKL,X + BEQ + + INC ESTKH,X ++ +-- STA $C05A ; ENABLE SLAVE + PHX + LDX #8 + LDY #0 ; ASSUME MSB IS ZERO + LDA (SRC),Y ; GET BYTE +- ASL + BCC + ; CHECK MSB + INY ; IT'S A ONE ++ STA $C058,Y ; WRITE BIT 7 + STA $C05C ; CLOCK FALLING EDGE + STA $C05D ; CLOCK RISING EDGE + LDY #0 + DEX + BNE - + STA $C05B ; DISABLE SLAVE + INC SRCL + BNE + + INC SRCH ++ PLX + DEC ESTKL,X + BNE -- + DEC ESTKH,X + BNE -- + INX ; REMOVE AN ARGUMENT + PLA + STA $C036 + PLP + RTS +end + +export def spiXferByte(outbyte) + return (spiReadWriteByte)(outbyte) +end + export def spiDelay(time) return call($FCA8, time, 0, 0, 0) // DELAY end @@ -203,7 +408,7 @@ export def spiSend(data) byte timeout, status for timeout = 1 to 100 step 10 - status = spiXferByte(data) + status = (spiReadWriteByte)(data) if status <> SPI_SLAVE_BUSY return status fin @@ -220,20 +425,20 @@ end export def spiWriteBuf(buf, len) spiSend(13) // CMD_BUF_WRITE spiSend(len >> 8); spiSend(len) - return spiWriteBytes(buf, len) + return (spiWriteBytes)(buf, len) end export def spiReadBuf(buf, len) spiSend(12) // CMD_BUF_READ spiSend(len >> 8); spiSend(len) - return spiReadBytes(buf, len) + return (spiReadBytes)(buf, len) end export def spiReady byte timeout timeout = 0xFF - while spiXferByte(0) <> SPI_SLAVE_READY and timeout // WAIT FOR READY + while (spiReadWriteByte)(0) <> SPI_SLAVE_READY and timeout // WAIT FOR READY timeout-- spiDelay(10) loop @@ -241,9 +446,19 @@ export def spiReady end export def spiReset - ^$C05B + ^$C05B // DISABLE SLAVE SELECT + ^$C05D // CLOCK RAISE (GS ONLY) return spiReady end +if call($FE1F, 0, 0, 0, 1).3 & 1 // GS ID ROUTINE + spiReadWriteByte = @spiXferByteStd + spiReadBytes = @spiReadBytesStd + spiWriteBytes = @spiWriteBytesStd +else + spiReadWriteByte = @spiXferByteGS + spiReadBytes = @spiReadBytesGS + spiWriteBytes = @spiWriteBytesGS +fin return spiReset <> 0 done From b19956b3ba281f16931d181bee68ede8e3fdc438 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Wed, 31 May 2017 18:31:04 -0700 Subject: [PATCH 48/58] On the road to 1.0 --- src/makefile | 82 +-- src/toolsrc/codegen.c | 603 ++++++++++++++-- src/toolsrc/codegen.h | 107 ++- src/toolsrc/lex.c | 16 +- src/toolsrc/lex.h | 1 + src/toolsrc/parse.c | 1089 ++++++++++++++--------------- src/toolsrc/plasm.c | 20 +- src/toolsrc/plasm.h | 16 + src/toolsrc/symbols.h | 13 +- src/vmsrc/a1cmd.pla | 156 +++-- src/vmsrc/cmd.pla | 1148 +++++++++++++++--------------- src/vmsrc/plvm.c | 94 ++- src/vmsrc/plvm01.s | 1543 ++++++++++++++++++++--------------------- src/vmsrc/plvm02.s | 439 ++++++------ src/vmsrc/plvm03.s | 33 +- src/vmsrc/plvmzp.inc | 6 +- src/vmsrc/soscmd.pla | 24 +- 17 files changed, 2994 insertions(+), 2396 deletions(-) mode change 100644 => 100755 src/makefile create mode 100755 src/toolsrc/plasm.h mode change 100644 => 100755 src/vmsrc/a1cmd.pla mode change 100644 => 100755 src/vmsrc/cmd.pla mode change 100644 => 100755 src/vmsrc/plvm02.s mode change 100644 => 100755 src/vmsrc/plvmzp.inc mode change 100644 => 100755 src/vmsrc/soscmd.pla diff --git a/src/makefile b/src/makefile old mode 100644 new mode 100755 index 36ec4bb..acce732 --- a/src/makefile +++ b/src/makefile @@ -44,8 +44,8 @@ MEMMGR = MEMMGR\#FE1000 MEMTEST = MEMTEST\#FE1000 FIBER = FIBER\#FE1000 PLASM = plasm -INCS = toolsrc/tokens.h toolsrc/symbols.h toolsrc/lex.h toolsrc/parse.h toolsrc/codegen.h -OBJS = toolsrc/plasm.c toolsrc/parse.o toolsrc/lex.o toolsrc/codegen.o +INCS = toolsrc/plasm.h toolsrc/tokens.h toolsrc/symbols.h toolsrc/lex.h toolsrc/parse.h toolsrc/codegen.h +OBJS = toolsrc/plasm.c toolsrc/parse.c toolsrc/lex.c toolsrc/codegen.c # # Image filetypes for Virtual ][ # @@ -83,20 +83,20 @@ $(PLVM): vmsrc/plvm.c cc vmsrc/plvm.c -o $(PLVM) vmsrc/a1cmd.a: vmsrc/a1cmd.pla $(PLASM) - ./$(PLASM) -A < vmsrc/a1cmd.pla > vmsrc/a1cmd.a + ./$(PLASM) -AO < vmsrc/a1cmd.pla > vmsrc/a1cmd.a $(PLVM01): vmsrc/plvm01.s vmsrc/a1cmd.a acme -o $(PLVM01) -l vmsrc/plvm01.sym vmsrc/plvm01.s $(CMD): vmsrc/cmd.pla vmsrc/cmdstub.s $(PLVM02) $(PLASM) - ./$(PLASM) -A < vmsrc/cmd.pla > vmsrc/cmd.a + ./$(PLASM) -AO < vmsrc/cmd.pla > vmsrc/cmd.a acme --setpc 8192 -o $(CMD) vmsrc/cmdstub.s $(PLVM02): vmsrc/plvm02.s acme -o $(PLVM02) -l vmsrc/plvm02.sym vmsrc/plvm02.s vmsrc/soscmd.a: vmsrc/soscmd.pla $(PLASM) - ./$(PLASM) -A < vmsrc/soscmd.pla > vmsrc/soscmd.a + ./$(PLASM) -AO < vmsrc/soscmd.pla > vmsrc/soscmd.a $(PLVM03): vmsrc/plvm03.s vmsrc/soscmd.a acme -o $(PLVM03) -l vmsrc/plvm03.sym vmsrc/plvm03.s @@ -105,143 +105,143 @@ $(PLVM03): vmsrc/plvm03.s vmsrc/soscmd.a # Sample code # test: samplesrc/test.pla samplesrc/testlib.pla $(PLVM) $(PLASM) - ./$(PLASM) -AM < samplesrc/test.pla > samplesrc/test.a + ./$(PLASM) -AMO < samplesrc/test.pla > samplesrc/test.a acme --setpc 4094 -o $(TEST) samplesrc/test.a - ./$(PLASM) -AM < samplesrc/testlib.pla > samplesrc/testlib.a + ./$(PLASM) -AMO < samplesrc/testlib.pla > samplesrc/testlib.a acme --setpc 4094 -o $(TESTLIB) samplesrc/testlib.a ./$(PLVM) TEST $(ED): toolsrc/ed.pla $(PLVM02) $(PLASM) toolsrc/ed.pla - ./$(PLASM) -A < toolsrc/ed.pla > toolsrc/ed.a + ./$(PLASM) -AO < toolsrc/ed.pla > toolsrc/ed.a acme --setpc 8192 -o $(ED) toolsrc/ed.a $(SB): toolsrc/sb.pla $(PLVM02) $(PLASM) toolsrc/sb.pla - ./$(PLASM) -A < toolsrc/sb.pla > toolsrc/sb.a + ./$(PLASM) -AO < toolsrc/sb.pla > toolsrc/sb.a acme --setpc 8192 -o $(SB) toolsrc/sb.a $(ARGS): libsrc/args.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/args.pla > libsrc/args.a + ./$(PLASM) -AMO < libsrc/args.pla > libsrc/args.a acme --setpc 4094 -o $(ARGS) libsrc/args.a $(MEMMGR): libsrc/memmgr.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/memmgr.pla > libsrc/memmgr.a + ./$(PLASM) -AMO < libsrc/memmgr.pla > libsrc/memmgr.a acme --setpc 4094 -o $(MEMMGR) libsrc/memmgr.a $(MEMTEST): samplesrc/memtest.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/memtest.pla > samplesrc/memtest.a + ./$(PLASM) -AMO < samplesrc/memtest.pla > samplesrc/memtest.a acme --setpc 4094 -o $(MEMTEST) samplesrc/memtest.a $(FIBER): libsrc/fiber.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/fiber.pla > libsrc/fiber.a + ./$(PLASM) -AMO < libsrc/fiber.pla > libsrc/fiber.a acme --setpc 4094 -o $(FIBER) libsrc/fiber.a $(MON): samplesrc/mon.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/mon.pla > samplesrc/mon.a + ./$(PLASM) -AMO < samplesrc/mon.pla > samplesrc/mon.a acme --setpc 4094 -o $(MON) samplesrc/mon.a $(ROD): samplesrc/rod.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/rod.pla > samplesrc/rod.a + ./$(PLASM) -AMO < samplesrc/rod.pla > samplesrc/rod.a acme --setpc 4094 -o $(ROD) samplesrc/rod.a $(SIEVE): samplesrc/sieve.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/sieve.pla > samplesrc/sieve.a + ./$(PLASM) -AMO < samplesrc/sieve.pla > samplesrc/sieve.a acme --setpc 4094 -o $(SIEVE) samplesrc/sieve.a $(UTHERNET): libsrc/uthernet.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/uthernet.pla > libsrc/uthernet.a + ./$(PLASM) -AMO < libsrc/uthernet.pla > libsrc/uthernet.a acme --setpc 4094 -o $(UTHERNET) libsrc/uthernet.a $(UTHERNET2): libsrc/uthernet2.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/uthernet2.pla > libsrc/uthernet2.a + ./$(PLASM) -AMO < libsrc/uthernet2.pla > libsrc/uthernet2.a acme --setpc 4094 -o $(UTHERNET2) libsrc/uthernet2.a $(ETHERIP): libsrc/etherip.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/etherip.pla > libsrc/etherip.a + ./$(PLASM) -AMO < libsrc/etherip.pla > libsrc/etherip.a acme --setpc 4094 -o $(ETHERIP) libsrc/etherip.a $(INET): libsrc/inet.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/inet.pla > libsrc/inet.a + ./$(PLASM) -AMO < libsrc/inet.pla > libsrc/inet.a acme --setpc 4094 -o $(INET) libsrc/inet.a $(DHCP): libsrc/dhcp.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/dhcp.pla > libsrc/dhcp.a + ./$(PLASM) -AMO < libsrc/dhcp.pla > libsrc/dhcp.a acme --setpc 4094 -o $(DHCP) libsrc/dhcp.a $(HTTPD): samplesrc/httpd.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/httpd.pla > samplesrc/httpd.a + ./$(PLASM) -AMO < samplesrc/httpd.pla > samplesrc/httpd.a acme --setpc 4094 -o $(HTTPD) samplesrc/httpd.a $(FILEIO): libsrc/fileio.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/fileio.pla > libsrc/fileio.a + ./$(PLASM) -AMO < libsrc/fileio.pla > libsrc/fileio.a acme --setpc 4094 -o $(FILEIO) libsrc/fileio.a $(TONE): libsrc/tone.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/tone.pla > libsrc/tone.a + ./$(PLASM) -AMO < libsrc/tone.pla > libsrc/tone.a acme --setpc 4094 -o $(TONE) libsrc/tone.a $(FATCAT): samplesrc/fatcat.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/fatcat.pla > samplesrc/fatcat.a + ./$(PLASM) -AMO < samplesrc/fatcat.pla > samplesrc/fatcat.a acme --setpc 4094 -o $(FATCAT) samplesrc/fatcat.a $(FATGET): samplesrc/fatget.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/fatget.pla > samplesrc/fatget.a + ./$(PLASM) -AMO < samplesrc/fatget.pla > samplesrc/fatget.a acme --setpc 4094 -o $(FATGET) samplesrc/fatget.a $(FATPUT): samplesrc/fatput.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/fatput.pla > samplesrc/fatput.a + ./$(PLASM) -AMO < samplesrc/fatput.pla > samplesrc/fatput.a acme --setpc 4094 -o $(FATPUT) samplesrc/fatput.a $(FATWDSK): samplesrc/fatwritedsk.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/fatwritedsk.pla > samplesrc/fatwritedsk.a + ./$(PLASM) -AMO < samplesrc/fatwritedsk.pla > samplesrc/fatwritedsk.a acme --setpc 4094 -o $(FATWDSK) samplesrc/fatwritedsk.a $(FATRDSK): samplesrc/fatreaddsk.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/fatreaddsk.pla > samplesrc/fatreaddsk.a + ./$(PLASM) -AMO < samplesrc/fatreaddsk.pla > samplesrc/fatreaddsk.a acme --setpc 4094 -o $(FATRDSK) samplesrc/fatreaddsk.a $(SDFAT): libsrc/sdfat.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/sdfat.pla > libsrc/sdfat.a + ./$(PLASM) -AMO < libsrc/sdfat.pla > libsrc/sdfat.a acme --setpc 4094 -o $(SDFAT) libsrc/sdfat.a $(SPIPORT): libsrc/spiport.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/spiport.pla > libsrc/spiport.a + ./$(PLASM) -AMO < libsrc/spiport.pla > libsrc/spiport.a acme --setpc 4094 -o $(SPIPORT) libsrc/spiport.a $(PORTIO): libsrc/portio.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/portio.pla > libsrc/portio.a + ./$(PLASM) -AMO < libsrc/portio.pla > libsrc/portio.a acme --setpc 4094 -o $(PORTIO) libsrc/portio.a $(DGR): libsrc/dgr.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < libsrc/dgr.pla > libsrc/dgr.a + ./$(PLASM) -AMO < libsrc/dgr.pla > libsrc/dgr.a acme --setpc 4094 -o $(DGR) libsrc/dgr.a $(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/dgrtest.pla > samplesrc/dgrtest.a + ./$(PLASM) -AMO < samplesrc/dgrtest.pla > samplesrc/dgrtest.a acme --setpc 4094 -o $(DGRTEST) samplesrc/dgrtest.a $(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a + ./$(PLASM) -AMO < samplesrc/rogue.pla > samplesrc/rogue.a acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a $(ROGUEIO): samplesrc/rogue.io.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/rogue.io.pla > samplesrc/rogue.io.a + ./$(PLASM) -AMO < samplesrc/rogue.io.pla > samplesrc/rogue.io.a acme --setpc 4094 -o $(ROGUEIO) samplesrc/rogue.io.a $(ROGUECOMBAT): samplesrc/rogue.combat.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/rogue.combat.pla > samplesrc/rogue.combat.a + ./$(PLASM) -AMO < samplesrc/rogue.combat.pla > samplesrc/rogue.combat.a acme --setpc 4094 -o $(ROGUECOMBAT) samplesrc/rogue.combat.a $(ROGUEMAP): samplesrc/rogue.map.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/rogue.map.pla > samplesrc/rogue.map.a + ./$(PLASM) -AMO < samplesrc/rogue.map.pla > samplesrc/rogue.map.a acme --setpc 4094 -o $(ROGUEMAP) samplesrc/rogue.map.a $(HGR1): samplesrc/hgr1.pla samplesrc/hgr1test.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AM < samplesrc/hgr1test.pla > samplesrc/hgr1test.a + ./$(PLASM) -AMO < samplesrc/hgr1test.pla > samplesrc/hgr1test.a acme --setpc 4094 -o $(HGR1TEST) samplesrc/hgr1test.a - ./$(PLASM) -AM < samplesrc/hgr1.pla > samplesrc/hgr1.a + ./$(PLASM) -AMO < samplesrc/hgr1.pla > samplesrc/hgr1.a acme --setpc 4094 -o $(HGR1) samplesrc/hgr1.a hello: samplesrc/hello.pla $(PLVM) $(PLASM) - ./$(PLASM) -AM < samplesrc/hello.pla > samplesrc/hello.a + ./$(PLASM) -AMO < samplesrc/hello.pla > samplesrc/hello.a acme --setpc 4094 -o $(HELLO) samplesrc/hello.a ./$(PLVM) HELLO diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index 0c1e299..9d0cfb8 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -1,10 +1,7 @@ #include #include #include -#include "tokens.h" -#include "lex.h" -#include "symbols.h" -#include "codegen.h" +#include "plasm.h" /* * Symbol table and fixup information. */ @@ -30,6 +27,8 @@ static int idlocal_offset[128]; static char fixup_size[2048]; static int fixup_type[2048]; static int fixup_tag[2048]; +static t_opseq optbl[256]; +static t_opseq *freeop_lst = &optbl[0]; #define FIXUP_BYTE 0x00 #define FIXUP_WORD 0x80 int id_match(char *name, int len, char *id) @@ -162,6 +161,11 @@ int id_add(char *name, int len, int type, int size) { return ((type & LOCAL_TYPE) ? idlocal_add(name, len, type, size) : idglobal_add(name, len, type, size)); } +void idlocal_reset(void) +{ + locals = 0; + localsize = 0; +} int idfunc_add(char *name, int len, int type, int tag) { if (globals > 1024) @@ -255,10 +259,6 @@ int fixup_new(int tag, int type, int size) /* * Emit assembly code. */ -#define BYTECODE_SEG 8 -#define INIT 16 -#define SYSFLAGS 32 -static int outflags = 0; static const char *DB = ".BYTE"; static const char *DW = ".WORD"; static const char *DS = ".RES"; @@ -305,8 +305,7 @@ void emit_dci(char *str, int len) } void emit_flags(int flags) { - outflags = flags; - if (outflags & ACME) + if (flags & ACME) { DB = "!BYTE"; DW = "!WORD"; @@ -316,6 +315,8 @@ void emit_flags(int flags) } void emit_header(void) { + int i; + if (outflags & ACME) printf("; ACME COMPATIBLE OUTPUT\n"); else @@ -324,7 +325,7 @@ void emit_header(void) { printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW); printf("_SEGBEGIN%c\n", LBL); - printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW); + printf("\t%s\t$DA7F\t\t\t; MAGIC #\n", DW); printf("\t%s\t_SYSFLAGS\t\t\t; SYSTEM FLAGS\n", DW); printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW); printf("\t%s\t_DEFCNT\t\t\t; BYTECODE DEF COUNT\n", DW); @@ -334,6 +335,12 @@ void emit_header(void) { printf("\tJMP\t_INIT\t\t\t; MODULE INITIALIZATION ROUTINE\n"); } + /* + * Init free op sequence table + */ + for (i = 0; i < sizeof(optbl)/sizeof(t_opseq)-1; i++) + optbl[i].nextop = &optbl[i+1]; + optbl[i].nextop = NULL; } void emit_rld(void) { @@ -448,9 +455,16 @@ void emit_idglobal(int tag, int size, char *name) else printf("_D%03d%c\t%s\t%d\t\t\t; %s\n", tag, LBL, DS, size, name); } -void emit_idfunc(int tag, int type, char *name) +void emit_idfunc(int tag, int type, char *name, int is_bytecode) { - printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name); + if (name) + printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name); + if (!(outflags & MODULE)) + { + //printf("%s%c\n", name, LBL); + if (is_bytecode) + printf("\tJSR\tINTERP\n"); + } } void emit_idconst(char *name, int value) { @@ -519,17 +533,6 @@ int emit_data(int vartype, int consttype, long constval, int constsize) } return (datasize); } -void emit_def(const char *name, int is_bytecode) -{ - if (!(outflags & MODULE)) - { - //printf("%s%c\n", name, LBL); - if (is_bytecode) - printf("\tJSR\tINTERP\n"); - } - locals = 0; - localsize = 0; -} void emit_codetag(int tag) { printf("_B%03d%c\n", tag, LBL); @@ -566,17 +569,31 @@ void emit_llw(int index) } void emit_lab(int tag, int offset, int type) { - int fixup = fixup_new(tag, type, FIXUP_WORD); - char *taglbl = tag_string(tag, type); - printf("\t%s\t$68\t\t\t; LAB\t%s+%d\n", DB, taglbl, offset); - printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + if (type) + { + int fixup = fixup_new(tag, type, FIXUP_WORD); + char *taglbl = tag_string(tag, type); + printf("\t%s\t$68\t\t\t; LAB\t%s+%d\n", DB, taglbl, offset); + printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + } + else + { + printf("\t%s\t$68,$%02X,$%02X\t\t; LAB\t%d\n", DB, offset&0xFF,(offset>>8)&0xFF, offset); + } } void emit_law(int tag, int offset, int type) { - int fixup = fixup_new(tag, type, FIXUP_WORD); - char *taglbl = tag_string(tag, type); - printf("\t%s\t$6A\t\t\t; LAW\t%s+%d\n", DB, taglbl, offset); - printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + if (type) + { + int fixup = fixup_new(tag, type, FIXUP_WORD); + char *taglbl = tag_string(tag, type); + printf("\t%s\t$6A\t\t\t; LAW\t%s+%d\n", DB, taglbl, offset); + printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + } + else + { + printf("\t%s\t$6A,$%02X,$%02X\t\t; LAW\t%d\n", DB, offset&0xFF,(offset>>8)&0xFF, offset); + } } void emit_sb(void) { @@ -604,31 +621,45 @@ void emit_dlw(int index) } void emit_sab(int tag, int offset, int type) { - int fixup = fixup_new(tag, type, FIXUP_WORD); - char *taglbl = tag_string(tag, type); - printf("\t%s\t$78\t\t\t; SAB\t%s+%d\n", DB, taglbl, offset); - printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + if (type) + { + int fixup = fixup_new(tag, type, FIXUP_WORD); + char *taglbl = tag_string(tag, type); + printf("\t%s\t$78\t\t\t; SAB\t%s+%d\n", DB, taglbl, offset); + printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + } + else + { + printf("\t%s\t$78,$%02X,$%02X\t\t; SAB\t%d\n", DB, offset&0xFF,(offset>>8)&0xFF, offset); + } } void emit_saw(int tag, int offset, int type) +{ + if (type) + { + int fixup = fixup_new(tag, type, FIXUP_WORD); + char *taglbl = tag_string(tag, type); + printf("\t%s\t$7A\t\t\t; SAW\t%s+%d\n", DB, taglbl, offset); + printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); + } + else + { + printf("\t%s\t$7A,$%02X,$%02X\t\t; SAW\t%d\n", DB, offset&0xFF,(offset>>8)&0xFF, offset); + } +} +void emit_dab(int tag, int offset, int type) { int fixup = fixup_new(tag, type, FIXUP_WORD); char *taglbl = tag_string(tag, type); - printf("\t%s\t$7A\t\t\t; SAW\t%s+%d\n", DB, taglbl, offset); + printf("\t%s\t$7C\t\t\t; DAB\t%s+%d\n", DB, taglbl, offset); printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); } -void emit_dab(int tag, int type) +void emit_daw(int tag, int offset, int type) { int fixup = fixup_new(tag, type, FIXUP_WORD); char *taglbl = tag_string(tag, type); - printf("\t%s\t$7C\t\t\t; DAB\t%s\n", DB, taglbl); - printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl); -} -void emit_daw(int tag, int type) -{ - int fixup = fixup_new(tag, type, FIXUP_WORD); - char *taglbl = tag_string(tag, type); - printf("\t%s\t$7E\t\t\t; DAW\t%s\n", DB, taglbl); - printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl); + printf("\t%s\t$7E\t\t\t; DAW\t%s+%d\n", DB, taglbl, offset); + printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset); } void emit_localaddr(int index) { @@ -725,27 +756,23 @@ void emit_start(void) outflags |= INIT; defs++; } -void emit_dup(void) +void emit_push_exp(void) { - printf("\t%s\t$32\t\t\t; DUP\n", DB); + printf("\t%s\t$34\t\t\t; PUSH EXP\n", DB); } -void emit_push(void) +void emit_pull_exp(void) { - printf("\t%s\t$34\t\t\t; PUSH\n", DB); -} -void emit_pull(void) -{ - printf("\t%s\t$36\t\t\t; PULL\n", DB); -} -void emit_swap(void) -{ - printf("\t%s\t$2E\t\t\t; SWAP\n", DB); + printf("\t%s\t$36\t\t\t; PULL EXP\n", DB); } void emit_drop(void) { printf("\t%s\t$30\t\t\t; DROP\n", DB); } -int emit_unaryop(int op) +void emit_dup(void) +{ + printf("\t%s\t$32\t\t\t; DUP\n", DB); +} +int emit_unaryop(t_token op) { switch (op) { @@ -841,3 +868,459 @@ int emit_op(t_token op) } return (1); } +/* + * New/release sequence ops + */ +t_opseq *new_op(void) +{ + t_opseq* op = freeop_lst; + if (!op) + { + fprintf(stderr, "Compiler out of sequence ops!\n"); + return (NULL); + } + freeop_lst = freeop_lst->nextop; + op->nextop = NULL; + return (op); +} +void release_op(t_opseq *op) +{ + if (op) + { + op->nextop = freeop_lst; + freeop_lst = op; + } +} +void release_seq(t_opseq *seq) +{ + t_opseq *op; + while (seq) + { + op = seq; + seq = seq->nextop; + /* + * Free this op + */ + op->nextop = freeop_lst; + freeop_lst = op; + } +} +/* + * Crunch sequence (peephole optimize) + */ +int crunch_seq(t_opseq *seq) +{ + t_opseq *opnext, *opnextnext; + t_opseq *op = seq; + int crunched = 0; + int freeops = 0; + while (op && (opnext = op->nextop)) + { + switch (op->code) + { + case CONST_CODE: + //fprintf(stderr, "CONST -> $%04X", opnext->code); + if (op->val == 1) + { + if (opnext->code == BINARY_CODE(ADD_TOKEN)) + { + op->code = INC_CODE; + freeops = 1; + break; + } + if (opnext->code == BINARY_CODE(SUB_TOKEN)) + { + op->code = DEC_CODE; + freeops = 1; + break; + } + } + switch (opnext->code) + { + case NEG_CODE: + op->val = -(op->val); + freeops = 1; + break; + case COMP_CODE: + op->val = ~(op->val); + freeops = 1; + break; + case LOGIC_NOT_CODE: + op->val = op->val ? 0 : 1; + freeops = 1; + break; + case UNARY_CODE(BPTR_TOKEN): + case LB_CODE: + op->offsz = op->val; + op->code = LAB_CODE; + freeops = 1; + break; + case UNARY_CODE(WPTR_TOKEN): + case LW_CODE: + op->offsz = op->val; + op->code = LAW_CODE; + freeops = 1; + break; + case SB_CODE: + op->offsz = op->val; + op->code = SAB_CODE; + freeops = 1; + break; + case SW_CODE: + op->offsz = op->val; + op->code = SAW_CODE; + freeops = 1; + break; + case CONST_CODE: // Collapse constant operation + if ((opnextnext = opnext->nextop)) + switch (opnextnext->code) + { + case BINARY_CODE(MUL_TOKEN): + op->val *= opnext->val; + freeops = 2; + break; + case BINARY_CODE(DIV_TOKEN): + op->val /= opnext->val; + freeops = 2; + break; + case BINARY_CODE(MOD_TOKEN): + op->val %= opnext->val; + freeops = 2; + break; + case BINARY_CODE(ADD_TOKEN): + op->val += opnext->val; + freeops = 2; + break; + case BINARY_CODE(SUB_TOKEN): + op->val -= opnext->val; + freeops = 2; + break; + case BINARY_CODE(SHL_TOKEN): + op->val <<= opnext->val; + freeops = 2; + break; + case BINARY_CODE(SHR_TOKEN): + op->val >>= opnext->val; + freeops = 2; + break; + case BINARY_CODE(AND_TOKEN): + op->val &= opnext->val; + freeops = 2; + break; + case BINARY_CODE(OR_TOKEN): + op->val |= opnext->val; + freeops = 2; + break; + case BINARY_CODE(EOR_TOKEN): + op->val ^= opnext->val; + freeops = 2; + break; + case BINARY_CODE(EQ_TOKEN): + op->val = op->val == opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(NE_TOKEN): + op->val = op->val != opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(GE_TOKEN): + op->val = op->val >= opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(LT_TOKEN): + op->val = op->val < opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(GT_TOKEN): + op->val = op->val > opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(LE_TOKEN): + op->val = op->val <= opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(LOGIC_OR_TOKEN): + op->val = op->val || opnext->val ? 1 : 0; + freeops = 2; + break; + case BINARY_CODE(LOGIC_AND_TOKEN): + op->val = op->val && opnext->val ? 1 : 0; + freeops = 2; + break; + } + break; // CONST_CODE + } + break; // CONST_CODE + case LADDR_CODE: + switch (opnext->code) + { + case CONST_CODE: + if ((opnextnext = opnext->nextop)) + switch (opnextnext->code) + { + case ADD_CODE: + case INDEXB_CODE: + op->offsz += opnext->val; + freeops = 2; + break; + case INDEXW_CODE: + op->offsz += opnext->val * 2; + freeops = 2; + break; + } + break; + case LB_CODE: + op->code = LLB_CODE; + freeops = 1; + break; + case LW_CODE: + op->code = LLW_CODE; + freeops = 1; + break; + case SB_CODE: + op->code = SLB_CODE; + freeops = 1; + break; + case SW_CODE: + op->code = SLW_CODE; + freeops = 1; + break; + } + break; // LADDR_CODE + case GADDR_CODE: + switch (opnext->code) + { + case CONST_CODE: + if ((opnextnext = opnext->nextop)) + switch (opnextnext->code) + { + case ADD_CODE: + case INDEXB_CODE: + op->offsz += opnext->val; + freeops = 2; + break; + case INDEXW_CODE: + op->offsz += opnext->val * 2; + freeops = 2; + break; + } + break; + case LB_CODE: + op->code = LAB_CODE; + freeops = 1; + break; + case LW_CODE: + op->code = LAW_CODE; + freeops = 1; + break; + case SB_CODE: + op->code = SAB_CODE; + freeops = 1; + break; + case SW_CODE: + op->code = SAW_CODE; + freeops = 1; + break; + case ICAL_CODE: + op->code = CALL_CODE; + freeops = 1; + break; + } + break; // GADDR_CODE + } + // + // Free up crunched ops + // + while (freeops) + { + op->nextop = opnext->nextop; + opnext->nextop = freeop_lst; + freeop_lst = opnext; + opnext = op->nextop; + crunched = 1; + freeops--; + } + op = opnext; + } + return (crunched); +} +/* + * Generate a sequence of code + */ +t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type) +{ + t_opseq *op; + + if (!seq) + { + op = seq = new_op(); + } + else + { + op = seq; + while (op->nextop) + op = op->nextop; + op->nextop = new_op(); + op = op->nextop; + } + op->code = opcode; + op->val = cval; + op->tag = tag; + op->offsz = offsz; + op->type = type; + return (seq); +} +/* + * Append one sequence to the end of another + */ +t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2) +{ + t_opseq *op; + + if (!seq1) + return (seq2); + for (op = seq1; op->nextop; op = op->nextop); + op->nextop = seq2; + return (seq1); +} +/* + * Emit a sequence of ops + */ +int emit_seq(t_opseq *seq) +{ + t_opseq *op; + + if (!seq) + return (0); + if (outflags & OPTIMIZE) + while (crunch_seq(seq)); + while (seq) + { + op = seq; + switch (op->code) + { + case NEG_CODE: + case COMP_CODE: + case LOGIC_NOT_CODE: + case INC_CODE: + case DEC_CODE: + case BPTR_CODE: + case WPTR_CODE: + emit_unaryop(op->code); + break; + case MUL_CODE: + case DIV_CODE: + case MOD_CODE: + case ADD_CODE: + case SUB_CODE: + case SHL_CODE: + case SHR_CODE: + case AND_CODE: + case OR_CODE: + case EOR_CODE: + case EQ_CODE: + case NE_CODE: + case GE_CODE: + case LT_CODE: + case GT_CODE: + case LE_CODE: + case LOGIC_OR_CODE: + case LOGIC_AND_CODE: + emit_op(op->code); + break; + case CONST_CODE: + emit_const(op->val); + break; + case STR_CODE: + emit_conststr(op->val, op->offsz); + break; + case LB_CODE: + emit_lb(); + break; + case LW_CODE: + emit_lw(); + break; + case LLB_CODE: + emit_llb(op->offsz); + break; + case LLW_CODE: + emit_llw(op->offsz); + break; + case LAB_CODE: + emit_lab(op->tag, op->offsz, op->type); + break; + case LAW_CODE: + emit_law(op->tag, op->offsz, op->type); + break; + case SB_CODE: + emit_sb(); + break; + case SW_CODE: + emit_sw(); + break; + case SLB_CODE: + emit_slb(op->offsz); + break; + case SLW_CODE: + emit_slw(op->offsz); + break; + case DLB_CODE: + emit_dlb(op->offsz); + break; + case DLW_CODE: + emit_dlw(op->offsz); + break; + case SAB_CODE: + emit_sab(op->tag, op->offsz, op->type); + break; + case SAW_CODE: + emit_saw(op->tag, op->offsz, op->type); + break; + case DAB_CODE: + emit_dab(op->tag, op->offsz, op->type); + break; + case DAW_CODE: + emit_daw(op->tag, op->offsz, op->type); + break; + case CALL_CODE: + emit_call(op->tag, op->type); + break; + case ICAL_CODE: + emit_ical(); + break; + case LADDR_CODE: + emit_localaddr(op->offsz); + break; + case GADDR_CODE: + emit_globaladdr(op->tag, op->offsz, op->type); + break; + case INDEXB_CODE: + emit_indexbyte(); + break; + case INDEXW_CODE: + emit_indexword(); + break; + case DROP_CODE: + emit_drop(); + break; + case DUP_CODE: + emit_dup(); + break; + case PUSH_EXP_CODE: + emit_push_exp(); + break; + case PULL_EXP_CODE: + emit_pull_exp(); + break; + default: + return (0); + } + seq = seq->nextop; + /* + * Free this op + */ + op->nextop = freeop_lst; + freeop_lst = op; + } + return (1); +} diff --git a/src/toolsrc/codegen.h b/src/toolsrc/codegen.h index d05d11c..f69c96b 100755 --- a/src/toolsrc/codegen.h +++ b/src/toolsrc/codegen.h @@ -1,5 +1,84 @@ -#define ACME 1 -#define MODULE 2 +typedef struct _opseq { + int code; + long val; + int tag; + int offsz; + int type; + struct _opseq *nextop; +} t_opseq; +#define UNARY_CODE(tkn) ((tkn)|0x0100) +#define BINARY_CODE(tkn) ((tkn)|0x0200) +#define NEG_CODE 0x0100|NEG_TOKEN +#define COMP_CODE 0x0100|COMP_TOKEN +#define LOGIC_NOT_CODE 0x0100|LOGIC_NOT_TOKEN +#define INC_CODE 0x0100|INC_TOKEN +#define DEC_CODE 0x0100|DEC_TOKEN +#define BPTR_CODE 0x0100|BPTR_TOKEN +#define WPTR_CODE 0x0100|WPTR_TOKEN +#define MUL_CODE 0x0200|MUL_TOKEN +#define DIV_CODE 0x0200|DIV_TOKEN +#define MOD_CODE 0x0200|MOD_TOKEN +#define ADD_CODE 0x0200|ADD_TOKEN +#define SUB_CODE 0x0200|SUB_TOKEN +#define SHL_CODE 0x0200|SHL_TOKEN +#define SHR_CODE 0x0200|SHR_TOKEN +#define AND_CODE 0x0200|AND_TOKEN +#define OR_CODE 0x0200|OR_TOKEN +#define EOR_CODE 0x0200|EOR_TOKEN +#define EQ_CODE 0x0200|EQ_TOKEN +#define NE_CODE 0x0200|NE_TOKEN +#define GE_CODE 0x0200|GE_TOKEN +#define LT_CODE 0x0200|LT_TOKEN +#define GT_CODE 0x0200|GT_TOKEN +#define LE_CODE 0x0200|LE_TOKEN +#define LOGIC_OR_CODE 0x0200|LOGIC_OR_TOKEN +#define LOGIC_AND_CODE 0x0200|LOGIC_AND_TOKEN +#define CONST_CODE 0x0300 +#define STR_CODE 0x0301 +#define LB_CODE 0x0302 +#define LW_CODE 0x0303 +#define LLB_CODE 0x0304 +#define LLW_CODE 0x0305 +#define LAB_CODE 0x0306 +#define LAW_CODE 0x0307 +#define SB_CODE 0x0308 +#define SW_CODE 0x0309 +#define SLB_CODE 0x030A +#define SLW_CODE 0x030B +#define DLB_CODE 0x030C +#define DLW_CODE 0x030D +#define SAB_CODE 0x030E +#define SAW_CODE 0x030F +#define DAB_CODE 0x0310 +#define DAW_CODE 0x0311 +#define CALL_CODE 0x0312 +#define ICAL_CODE 0x0313 +#define LADDR_CODE 0x0314 +#define GADDR_CODE 0x0315 +#define INDEXB_CODE 0x0316 +#define INDEXW_CODE 0x0317 +#define DROP_CODE 0x0318 +#define DUP_CODE 0x0319 +#define PUSH_EXP_CODE 0x031A +#define PULL_EXP_CODE 0x031B + +#define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0) +#define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0) +#define gen_const(seq,val) gen_seq(seq,CONST_CODE,val,0,0,0) +#define gen_str(seq,str,len) gen_seq(seq,STR_CODE,str,0,len,0) +#define gen_lcladr(seq,idx) gen_seq(seq,LADDR_CODE,0,0,idx,0) +#define gen_gbladr(seq,tag,typ) gen_seq(seq,GADDR_CODE,0,tag,0,typ) +#define gen_idxb(seq) gen_seq(seq,ADD_CODE,0,0,0,0) +#define gen_idxw(seq) gen_seq(seq,INDEXW_CODE,0,0,0,0) +#define gen_lb(seq) gen_seq(seq,LB_CODE,0,0,0,0) +#define gen_lw(seq) gen_seq(seq,LW_CODE,0,0,0,0) +#define gen_sb(seq) gen_seq(seq,SB_CODE,0,0,0,0) +#define gen_sw(seq) gen_seq(seq,SW_CODE,0,0,0,0) +#define gen_icall(seq) gen_seq(seq,ICAL_CODE,0,0,0,0) +#define gen_pushexp(seq) gen_seq(seq,PUSH_EXP_CODE,0,0,0,0) +#define gen_pullexp(seq) gen_seq(seq,PULL_EXP_CODE,0,0,0,0) +#define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0) + void emit_flags(int flags); void emit_header(void); void emit_trailer(void); @@ -10,9 +89,8 @@ void emit_comment(char *s); void emit_asm(char *s); void emit_idlocal(char *name, int value); void emit_idglobal(int value, int size, char *name); -void emit_idfunc(int tag, int type, char *name); +void emit_idfunc(int tag, int type, char *name, int is_bytecode); void emit_idconst(char *name, int value); -void emit_def(const char *name, int is_bytecode); int emit_data(int vartype, int consttype, long constval, int constsize); void emit_codetag(int tag); void emit_const(int cval); @@ -30,16 +108,16 @@ void emit_slw(int index); void emit_dlb(int index); void emit_dlw(int index); void emit_sab(int tag, int offset, int type); -void emit_saw(int tag, int ofset, int type); -void emit_dab(int tag, int type); -void emit_daw(int tag, int type); +void emit_saw(int tag, int offset, int type); +void emit_dab(int tag, int offset, int type); +void emit_daw(int tag, int offset, int type); void emit_call(int tag, int type); void emit_ical(void); void emit_localaddr(int index); void emit_globaladdr(int tag, int offset, int type); void emit_indexbyte(void); void emit_indexword(void); -int emit_unaryop(int op); +int emit_unaryop(t_token op); int emit_op(t_token op); void emit_brtru(int tag); void emit_brfls(int tag); @@ -47,14 +125,19 @@ void emit_brgt(int tag); void emit_brlt(int tag); void emit_brne(int tag); void emit_brnch(int tag); -void emit_swap(void); -void emit_dup(void); -void emit_push(void); -void emit_pull(void); +void emit_empty(void); +void emit_push_exp(void); +void emit_pull_exp(void); void emit_drop(void); +void emit_dup(void); void emit_leave(void); void emit_ret(void); void emit_enter(int cparams); void emit_start(void); void emit_rld(void); void emit_esd(void); +void release_seq(t_opseq *seq); +int crunch_seq(t_opseq *seq); +t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type); +t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2); +int emit_seq(t_opseq *seq); diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index f2294cb..77ae0ca 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -13,8 +13,7 @@ #include #include #include -#include "tokens.h" -#include "symbols.h" +#include "plasm.h" char *statement, *tokenstr, *scanpos = (char*) ""; t_token scantoken, prevtoken; @@ -66,6 +65,8 @@ t_token keywords[] = { EOL_TOKEN }; +extern int outflags; + void parse_error(const char *errormsg) { char *error_carrot = statement; @@ -76,7 +77,18 @@ void parse_error(const char *errormsg) fprintf(stderr, "^\nError: %s\n", errormsg); exit(1); } +void parse_warn(const char *warnmsg) +{ + if (outflags & WARNINGS) + { + char *error_carrot = statement; + fprintf(stderr, "\n%s %4d: %s\n%*s ", filename, lineno, statement, (int)strlen(filename), ""); + for (error_carrot = statement; error_carrot != tokenstr; error_carrot++) + putc(*error_carrot == '\t' ? '\t' : ' ', stderr); + fprintf(stderr, "^\nWarning: %s\n", warnmsg); + } +} int hexdigit(char ch) { ch = toupper(ch); diff --git a/src/toolsrc/lex.h b/src/toolsrc/lex.h index cf12a95..07033b5 100755 --- a/src/toolsrc/lex.h +++ b/src/toolsrc/lex.h @@ -4,6 +4,7 @@ extern int tokenlen; extern long constval; extern char inputline[]; void parse_error(const char *errormsg); +void parse_warn(const char *warnmsg); int next_line(void); void scan_rewind(char *backptr); int scan_lookahead(void); diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index a04986a..a9aeb2f 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -1,11 +1,9 @@ #include -#include "tokens.h" -#include "symbols.h" -#include "lex.h" -#include "codegen.h" -#include "parse.h" - +#include "plasm.h" +#define LVALUE 0 +#define RVALUE 1 int infunc = 0, break_tag = 0, cont_tag = 0, stack_loop = 0; +long infuncvals = 0; t_token prevstmnt; t_token binary_ops_table[] = { @@ -221,7 +219,7 @@ int parse_constval(void) { case CLOSE_PAREN_TOKEN: break; - case STRING_TOKEN: + case STRING_TOKEN: size = tokenlen - 1; value = constval; type = STRING_TYPE; @@ -340,406 +338,347 @@ int parse_const(long *value) /* * Normal expression parsing */ -int parse_expr(void); -int parse_term(void) +t_opseq *parse_expr(t_opseq *codeseq, int *stackdepth); +t_opseq *parse_list(t_opseq *codeseq, int *stackdepth) { - /* - * Parse terminal tokens. - */ - switch (scan()) + int parmdepth; + t_opseq *parmseq; + if (stackdepth) + *stackdepth = 0; + while ((parmseq = parse_expr(codeseq, &parmdepth))) { - case CHAR_TOKEN: - case INT_TOKEN: - case ID_TOKEN: - case STRING_TOKEN: + codeseq = parmseq; + if (stackdepth) + *stackdepth += parmdepth; + if (scantoken != COMMA_TOKEN) break; - case OPEN_PAREN_TOKEN: - if (!parse_expr()) - { - parse_error("Bad expression in parenthesis"); - return (0); - } - if (scantoken != CLOSE_PAREN_TOKEN) - { - parse_error("Missing closing parenthesis"); - return (0); - } - break; - default: - /* - * Non-terminal token. - */ - return (0); } - return (1); + return (codeseq); } -int parse_value(int rvalue) +t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth) { - int cparams; int deref = rvalue; - int optos = opsptr; - int type = 0, value = 0, emit_value = 0; - int ref_type, const_size; - long ref_offset, const_offset; + int type = 0, value = 0; + int cfnparms = 0; + long cfnvals = 1; + long const_offset; + t_opseq *uopseq = NULL; + t_opseq *valseq = NULL; + t_opseq *idxseq = NULL; + + if (stackdepth) + *stackdepth = 1; /* - * Parse pre operand operators. + * Parse pre operators. */ - while (!parse_term()) + while (scan()) { - switch (scantoken) + if (scantoken == ADD_TOKEN) { - case ADD_TOKEN: - /* - * Just ignore unary plus, it is a no-op. - */ - break; - case BPTR_TOKEN: - if (deref) - push_op(scantoken, 0); - else - { - deref++; - type |= BPTR_TYPE; - } - break; - case WPTR_TOKEN: - if (deref) - push_op(scantoken, 0); - else - { - deref++; - type |= WPTR_TYPE; - } - break; - case AT_TOKEN: - deref--; - break; - case NEG_TOKEN: - case COMP_TOKEN: - case LOGIC_NOT_TOKEN: - push_op(scantoken, 0); - break; - default: - return (0); + /* + * Just ignore unary plus, it is a no-op. + */ + } + else if (scantoken == AT_TOKEN) + { + if (deref-- == 0) + { + parse_error("Invalid ADDRESS-OF op"); + return (NULL); + } + } + else if (scantoken == BPTR_TOKEN || scantoken == WPTR_TOKEN) + { + deref++; + type |= scantoken == BPTR_TOKEN ? BPTR_TYPE : WPTR_TYPE; + } + else if (scantoken == NEG_TOKEN || scantoken == COMP_TOKEN || scantoken == LOGIC_NOT_TOKEN) + { + if (!rvalue) + { + parse_error("Invalid op for LVALUE"); + return (NULL); + } + uopseq = gen_uop(uopseq, scantoken); } - } - /* - * Determine which terminal type. - */ - if (scantoken == INT_TOKEN || scantoken == CHAR_TOKEN) - { - value = constval; - type |= CONST_TYPE; - } - else if (scantoken == ID_TOKEN) - { - if ((type |= id_type(tokenstr, tokenlen)) & CONST_TYPE) - value = id_const(tokenstr, tokenlen); - else if (type & VAR_TYPE) - value = id_tag(tokenstr, tokenlen); - else if (type & FUNC_TYPE) - value = id_tag(tokenstr, tokenlen); else - { - printf("Bad ID type\n"); - return (0); - } + break; } - else if (scantoken == CLOSE_PAREN_TOKEN) - { - // type |= WORD_TYPE; - emit_value = 1; - } - else if (scantoken == STRING_TOKEN) + /* + * Determine which value type. + */ + if (scantoken == STRING_TOKEN) { /* * This is a special case. Just emit the string and return */ - emit_conststr(constval, tokenlen - 1); + codeseq = gen_str(codeseq, constval, tokenlen - 1); scan(); - return WORD_TYPE; + return (codeseq); } - else - return (0); - if (type & CONST_TYPE) + if (scantoken == INT_TOKEN || scantoken == CHAR_TOKEN) { - /* - * Quick optimizations - */ - while ((optos < opsptr) - && ((tos_op() == NEG_TOKEN) || (tos_op() == COMP_TOKEN) || (tos_op() == LOGIC_NOT_TOKEN))) + value = constval; + type |= CONST_TYPE; + valseq = gen_const(NULL, value); + } + else if (scantoken == ID_TOKEN) + { + if ((type |= id_type(tokenstr, tokenlen)) & CONST_TYPE) { - switch (pop_op()) - { - case NEG_TOKEN: - value = -value; - break; - case COMP_TOKEN: - value = ~value; - break; - case LOGIC_NOT_TOKEN: - value = value ? 0 : -1; - break; - } + value = id_const(tokenstr, tokenlen); + valseq = gen_const(NULL, value); + } + else //if (type & (VAR_TYPE | FUNC_TYPE)) + { + value = id_tag(tokenstr, tokenlen); + if (type & LOCAL_TYPE) + valseq = gen_lcladr(NULL, value); + else + valseq = gen_gbladr(NULL, value, type); + } + if (type & FUNC_TYPE) + { + cfnparms = funcparms_cnt(type); + cfnvals = funcvals_cnt(type); } } - /* - * Parse post operand operators. - */ - ref_type = type & ~PTR_TYPE; - ref_offset = 0; - while (scan() == OPEN_PAREN_TOKEN - || scantoken == OPEN_BRACKET_TOKEN - || scantoken == PTRB_TOKEN - || scantoken == PTRW_TOKEN - || scantoken == DOT_TOKEN - || scantoken == COLON_TOKEN) + else if (scantoken == OPEN_PAREN_TOKEN) { - switch (scantoken) + if (!(valseq = parse_expr(NULL, stackdepth))) { - case OPEN_PAREN_TOKEN: + parse_error("Bad expression in parenthesis"); + return (NULL); + } + if (scantoken != CLOSE_PAREN_TOKEN) + { + parse_error("Missing closing parenthesis"); + return (NULL); + } + } + else + return (NULL); + /* + * Parse post operators. + */ + while (scan()) + { + if (scantoken == OPEN_PAREN_TOKEN) + { + /* + * Function call - parameters generate before call address + */ + valseq = cat_seq(parse_list(NULL, &value), valseq); + if (scantoken != CLOSE_PAREN_TOKEN) + { + parse_error("Missing closing parenthesis"); + return (NULL); + } + if (scan() == POUND_TOKEN) + { /* - * Function call + * Override return vals count */ - if (emit_value) + if (!parse_const(&cfnvals)) { - if (ref_offset != 0) - { - emit_const(ref_offset); - emit_op(ADD_TOKEN); - ref_offset = 0; - } - if (ref_type & PTR_TYPE) - (ref_type & BPTR_TYPE) ? emit_lb() : emit_lw(); - if (scan_lookahead() != CLOSE_PAREN_TOKEN) - emit_push(); - } - cparams = 0; - while (parse_expr()) - { - cparams++; - if (scantoken != COMMA_TOKEN) - break; - } - if (scantoken != CLOSE_PAREN_TOKEN) - { - parse_error("Missing closing parenthesis"); + parse_error("Invalid def return value count"); return (0); } - if (ref_type & (FUNC_TYPE | CONST_TYPE)) - emit_call(value, ref_type); - else - { - if (!emit_value) - { - if (type & CONST_TYPE) - emit_const(value); - else if (type & VAR_TYPE) - { - if (type & LOCAL_TYPE) - emit_llw(value + ref_offset); - else - emit_law(value, ref_offset, type); - ref_offset = 0; - } - } - else - if (cparams) - emit_pull(); - emit_ical(); - } - emit_value = 1; - ref_type = 0; - break; - case OPEN_BRACKET_TOKEN: + } + else + scan_rewind(tokenstr); + if (cfnparms && (cfnparms != value)) + parse_warn("Parameter count mismatch"); + if (stackdepth) + *stackdepth = cfnvals + cfnparms - value; + if (type & (VAR_TYPE | PTR_TYPE)) //!(type & (FUNC_TYPE | CONST_TYPE))) + { + valseq = gen_lw(valseq); + if (deref) + deref--; + } + valseq = gen_icall(valseq); + if (stackdepth) + *stackdepth = cfnvals; + cfnvals = 1; + type &= ~FUNC_TYPE; + } + else if (scantoken == OPEN_BRACKET_TOKEN) + { + /* + * Array of arrays + */ + if (type & FUNC_TYPE) + { /* - * Array of arrays + * Function call dereference */ - if (!emit_value) - { - if (type & CONST_TYPE) - emit_const(value); - else if (type & ADDR_TYPE) - { - if (type & LOCAL_TYPE) - emit_localaddr(value + ref_offset); - else - emit_globaladdr(value, ref_offset, type); - ref_offset = 0; - } - else - { - parse_error("Bad index reference"); - return (0); - } - emit_value = 1; - } - else - { - if (ref_offset != 0) - { - emit_const(ref_offset); - emit_op(ADD_TOKEN); - ref_offset = 0; - } - } - while (parse_expr()) - { - if (scantoken != COMMA_TOKEN) - break; - emit_indexword(); - emit_lw(); - } - if (scantoken != CLOSE_BRACKET_TOKEN) - { - parse_error("Missing closing bracket"); - return (0); - } - if (ref_type & (WPTR_TYPE | WORD_TYPE)) - { - emit_indexword(); - ref_type = WPTR_TYPE; - } - else - { - emit_indexbyte(); - ref_type = BPTR_TYPE; - } - break; - case PTRB_TOKEN: - case PTRW_TOKEN: + valseq = gen_icall(valseq); + if (stackdepth) + *stackdepth = cfnvals; + } + while ((idxseq = parse_expr(NULL, stackdepth))) + { + valseq = cat_seq(valseq, idxseq); + if (scantoken != COMMA_TOKEN) + break; + valseq = gen_idxw(valseq); + valseq = gen_lw(valseq); + } + if (scantoken != CLOSE_BRACKET_TOKEN) + { + parse_error("Missing closing bracket"); + return (NULL); + } + if (type & (WPTR_TYPE | WORD_TYPE)) + { + valseq = gen_idxw(valseq); + type = WPTR_TYPE; + } + else + { + valseq = gen_idxb(valseq); + type = BPTR_TYPE; + } + } + else if (scantoken == PTRB_TOKEN || scantoken == PTRW_TOKEN) + { + /* + * Pointer to structure/array + */ + if (type & FUNC_TYPE) + { + /* + * Function call dereference + */ + valseq = gen_icall(valseq); + if (stackdepth) + *stackdepth = cfnvals; + type &= ~FUNC_TYPE; + } + else if (type & VAR_TYPE) + { + /* + * Pointer dereference + */ + valseq = gen_lw(valseq); + } + type = (scantoken == PTRB_TOKEN) ? BPTR_TYPE : WPTR_TYPE; + if (!parse_const(&const_offset)) + { + /* + * Setting type override for following operations + */ + scan_rewind(tokenstr); + } + else if (const_offset != 0) + { /* * Structure member pointer */ - if (!emit_value) - { - if (type & CONST_TYPE) - emit_const(value); - else if (type & ADDR_TYPE) - { - if (type & LOCAL_TYPE) - (ref_type & BYTE_TYPE) ? emit_llb(value + ref_offset) : emit_llw(value + ref_offset); - else - (ref_type & BYTE_TYPE) ? emit_lab(value, ref_offset, type) : emit_law(value, ref_offset, type); - } - emit_value = 1; - } - else - { - if (ref_offset != 0) - { - emit_const(ref_offset); - emit_op(ADD_TOKEN); - } - if (ref_type & PTR_TYPE) - (ref_type & BPTR_TYPE) ? emit_lb() : emit_lw(); - } - ref_offset = 0; - ref_type = (scantoken == PTRB_TOKEN) ? BPTR_TYPE : WPTR_TYPE; - if (!parse_const(&ref_offset)) - scan_rewind(tokenstr); - if (ref_offset != 0) - { - emit_const(ref_offset); - emit_op(ADD_TOKEN); - ref_offset = 0; - } - break; - case DOT_TOKEN: - case COLON_TOKEN: + valseq = gen_const(valseq, const_offset); + valseq = gen_op(valseq, ADD_TOKEN); + } + } + else if (scantoken == DOT_TOKEN || scantoken == COLON_TOKEN) + { + /* + * Structure/array offset + */ + if (type & FUNC_TYPE) + { + /* + * Function call dereference + */ + valseq = gen_icall(valseq); + if (stackdepth) + *stackdepth = cfnvals; + type &= ~FUNC_TYPE; + } + type = (type & (VAR_TYPE | CONST_TYPE)) + ? ((scantoken == DOT_TOKEN) ? BYTE_TYPE : WORD_TYPE) + : ((scantoken == DOT_TOKEN) ? BPTR_TYPE : WPTR_TYPE); + if (!parse_const(&const_offset)) + { + /* + * Setting type override for following operations + */ + scan_rewind(tokenstr); + } + else if (const_offset != 0) + { /* * Structure member offset */ - ref_type = (ref_type & (VAR_TYPE | CONST_TYPE)) - ? ((scantoken == DOT_TOKEN) ? BYTE_TYPE : WORD_TYPE) - : ((scantoken == DOT_TOKEN) ? BPTR_TYPE : WPTR_TYPE); - if (parse_const(&const_offset)) - ref_offset += const_offset; - else - scan_rewind(tokenstr); - if (!emit_value) - { - if (type & CONST_TYPE) - { - value += ref_offset; - ref_offset = 0; - } - else if (type & FUNC_TYPE) - { - emit_globaladdr(value, ref_offset, type); - ref_offset = 0; - emit_value = 1; - } - } - break; - } - } - if (emit_value) - { - if (ref_offset != 0) - { - emit_const(ref_offset); - emit_op(ADD_TOKEN); - ref_offset = 0; - } - if (deref) - { - if (ref_type & BPTR_TYPE) emit_lb(); - else if (ref_type & WPTR_TYPE) emit_lw(); - } - } - else - { - if (deref) - { - if (type & CONST_TYPE) - { - emit_const(value); - if (ref_type & VAR_TYPE) - (ref_type & BYTE_TYPE) ? emit_lb() : emit_lw(); - } - else if (type & FUNC_TYPE) - emit_call(value, ref_type); - else if (type & VAR_TYPE) - { - if (type & LOCAL_TYPE) - (ref_type & BYTE_TYPE) ? emit_llb(value + ref_offset) : emit_llw(value + ref_offset); - else - (ref_type & BYTE_TYPE) ? emit_lab(value, ref_offset, ref_type) : emit_law(value, ref_offset, ref_type); + valseq = gen_const(valseq, const_offset); + valseq = gen_op(valseq, ADD_TOKEN); } } else - { - if (type & CONST_TYPE) - emit_const(value); - else if (type & ADDR_TYPE) - { - if (type & LOCAL_TYPE) - emit_localaddr(value + ref_offset); - else - emit_globaladdr(value, ref_offset, ref_type); - } - } + break; } - while (optos < opsptr) + /* + * Resolve outstanding dereference pointer loads + */ + while (deref > rvalue) { - if (!emit_unaryop(pop_op())) + deref--; + if (type & FUNC_TYPE) { - parse_error(": Invalid unary operation"); - return (0); + valseq = gen_icall(valseq); + if (stackdepth) + *stackdepth = cfnvals; + type &= ~FUNC_TYPE; + } + else if (type & VAR_TYPE) + valseq = gen_lw(valseq); + } + if (deref) + { + if (type & FUNC_TYPE) + { + valseq = gen_icall(valseq); + if (stackdepth) + *stackdepth = cfnvals; + type &= ~FUNC_TYPE; + } + else if (type & (BYTE_TYPE | BPTR_TYPE)) + valseq = gen_lb(valseq); + else if (type & (WORD_TYPE | WPTR_TYPE)) + valseq = gen_lw(valseq); + } + /* + * Output pre-operations + */ + valseq = cat_seq(valseq, uopseq); + /* + * Wrap up LVALUE store + */ + if (!rvalue) + { + if (type & (BYTE_TYPE | BPTR_TYPE)) + valseq = gen_sb(valseq); + else if (type & (WORD_TYPE | WPTR_TYPE)) + valseq = gen_sw(valseq); + else + { + release_seq(valseq); + return (NULL); // Function or const cannot be LVALUE, must be RVALUE } } - if (type & PTR_TYPE) - ref_type = type; - return (ref_type ? ref_type : WORD_TYPE); + return (cat_seq(codeseq, valseq)); } -int parse_expr() +t_opseq *parse_expr(t_opseq *codeseq, int *stackdepth) { int prevmatch; int matchop = 0; int optos = opsptr; - int i; + int i, valdepth; int prevtype, type = 0; + t_opseq *valseq; + + if (stackdepth) + *stackdepth = 0; do { /* @@ -747,42 +686,85 @@ int parse_expr() */ prevmatch = matchop; matchop = 0; - if (parse_value(1)) + if ((valseq = parse_value(NULL, RVALUE, &valdepth))) { + codeseq = cat_seq(codeseq, valseq); matchop = 1; + if (stackdepth) + *stackdepth += valdepth; for (i = 0; i < sizeof(binary_ops_table); i++) if (scantoken == binary_ops_table[i]) { matchop = 2; if (binary_ops_precedence[i] >= tos_op_prec(optos)) - if (!emit_op(pop_op())) - { - parse_error(": Invalid binary operation"); - return (0); - } + { + codeseq = gen_op(codeseq, pop_op()); + if (stackdepth) + (*stackdepth)--; + } push_op(scantoken, binary_ops_precedence[i]); break; } } - } - while (matchop == 2); + } while (matchop == 2); if (matchop == 0 && prevmatch == 2) { parse_error("Missing operand"); - return (0); + return (NULL); } while (optos < opsptr) - if (!emit_op(pop_op())) - { - parse_error(": Invalid binary operation"); - return (0); - } - return (matchop || prevmatch); + { + codeseq = gen_op(codeseq, pop_op()); + if (stackdepth) + (*stackdepth)--; + } + return (codeseq); +} +t_opseq *parse_set(t_opseq *codeseq) +{ + char *setptr = tokenstr; + int lparms = 0, rparms = 0; + int i; + t_opseq *setseq[16], *rseq = NULL; + + while ((setseq[lparms] = parse_value(NULL, LVALUE, NULL))) + { + lparms++; + if (scantoken != COMMA_TOKEN) + break; + } + if (lparms == 0 || scantoken != SET_TOKEN) + { + tokenstr = setptr; + scan_rewind(tokenstr); + while (lparms--) + release_seq(setseq[lparms]); + return (NULL); + } + rseq = parse_list(NULL, &rparms); + if (lparms > rparms) + { + parse_error("Set value list underflow"); + return (NULL); + } + if ((lparms != rparms) && (rparms - lparms != 1)) + codeseq = gen_pushexp(codeseq); + codeseq = cat_seq(codeseq, rseq); + for (i = lparms - 1; i >= 0; i--) + codeseq = cat_seq(codeseq, setseq[i]); + if (lparms != rparms) + { + if (rparms - lparms == 1) + codeseq = gen_drop(codeseq); + else + codeseq = gen_pullexp(codeseq); + } + return (codeseq); } int parse_stmnt(void) { int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of; - int type, addr, step; + int type, addr, step, cfnvals; char *idptr; /* @@ -793,7 +775,7 @@ int parse_stmnt(void) switch (scantoken) { case IF_TOKEN: - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); @@ -802,21 +784,21 @@ int parse_stmnt(void) tag_endif = tag_new(BRANCH_TYPE); emit_brfls(tag_else); scan(); - do { + do + { while (parse_stmnt()) next_line(); if (scantoken != ELSEIF_TOKEN) break; emit_brnch(tag_endif); emit_codetag(tag_else); - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } tag_else = tag_new(BRANCH_TYPE); emit_brfls(tag_else); - } - while (1); + } while (1); if (scantoken == ELSE_TOKEN) { emit_brnch(tag_endif); @@ -844,7 +826,7 @@ int parse_stmnt(void) tag_prevbrk = break_tag; break_tag = tag_wend; emit_codetag(tag_while); - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); @@ -877,7 +859,7 @@ int parse_stmnt(void) } emit_codetag(cont_tag); cont_tag = tag_prevcnt; - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); @@ -905,7 +887,7 @@ int parse_stmnt(void) parse_error("Missing FOR ="); return (0); } - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad FOR expression"); return (0); @@ -914,7 +896,7 @@ int parse_stmnt(void) if (type & LOCAL_TYPE) type & BYTE_TYPE ? emit_dlb(addr) : emit_dlw(addr); else - type & BYTE_TYPE ? emit_dab(addr, type) : emit_daw(addr, type); + type & BYTE_TYPE ? emit_dab(addr, 0, type) : emit_daw(addr, 0, type); if (scantoken == TO_TOKEN) step = 1; else if (scantoken == DOWNTO_TOKEN) @@ -924,7 +906,7 @@ int parse_stmnt(void) parse_error("Missing FOR TO"); return (0); } - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad FOR TO expression"); return (0); @@ -932,7 +914,7 @@ int parse_stmnt(void) step > 0 ? emit_brgt(break_tag) : emit_brlt(break_tag); if (scantoken == STEP_TOKEN) { - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad FOR STEP expression"); return (0); @@ -960,7 +942,7 @@ int parse_stmnt(void) break_tag = tag_new(BRANCH_TYPE); tag_choice = tag_new(BRANCH_TYPE); tag_of = tag_new(BRANCH_TYPE); - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad CASE expression"); return (0); @@ -970,7 +952,7 @@ int parse_stmnt(void) { if (scantoken == OF_TOKEN) { - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) { parse_error("Bad CASE OF expression"); return (0); @@ -1037,13 +1019,17 @@ int parse_stmnt(void) int i; for (i = 0; i < stack_loop; i++) emit_drop(); - if (!parse_expr()) + cfnvals = 0; + emit_seq(parse_list(NULL, &cfnvals)); + if (cfnvals != infuncvals) + parse_warn("Inconsistent return value count"); + while (cfnvals++ < infuncvals) emit_const(0); emit_leave(); } else { - if (!parse_expr()) + if (!emit_seq(parse_expr(NULL, NULL))) emit_const(0); emit_ret(); } @@ -1064,123 +1050,46 @@ int parse_stmnt(void) case DONE_TOKEN: case DEF_TOKEN: return (0); - case ID_TOKEN: - idptr = tokenstr; - type = id_type(tokenstr, tokenlen); - addr = id_tag(tokenstr, tokenlen); - if (type & VAR_TYPE) - { - int elem_type = type; - long elem_offset = 0; - if (scan() == DOT_TOKEN || scantoken == COLON_TOKEN) - { - /* - * Structure member offset - */ - int elem_size; - elem_type = (scantoken == DOT_TOKEN) ? BYTE_TYPE : WORD_TYPE; - if (!parse_const(&elem_offset)) - scantoken = ID_TOKEN; - else - scan(); - } - if (scantoken == SET_TOKEN) - { - if (!parse_expr()) - { - parse_error("Bad expression"); - return (0); - } - if (type & LOCAL_TYPE) - (elem_type & BYTE_TYPE) ? emit_slb(addr + elem_offset) : emit_slw(addr + elem_offset); - else - (elem_type & BYTE_TYPE) ? emit_sab(addr, elem_offset, type) : emit_saw(addr, elem_offset, type); - break; - } - else if (scantoken == INC_TOKEN || scantoken == DEC_TOKEN) - { - if (type & LOCAL_TYPE) - { - if (elem_type & BYTE_TYPE) - { - emit_llb(addr + elem_offset); emit_unaryop(scantoken); emit_slb(addr + elem_offset); - } - else - { - emit_llw(addr + elem_offset); emit_unaryop(scantoken); emit_slw(addr + elem_offset); - } - } - else - { - if (elem_type & BYTE_TYPE) - { - emit_lab(addr, elem_offset, type); emit_unaryop(scantoken); emit_sab(addr, elem_offset, type); - } - else - { - emit_law(addr, elem_offset, type); emit_unaryop(scantoken); emit_saw(addr, elem_offset, type); - } - } - break; - } - } - else if (type & FUNC_TYPE) - { - if (scan() == EOL_TOKEN) - { - emit_call(addr, type); - emit_drop(); - break; - } - } - tokenstr = idptr; default: scan_rewind(tokenstr); - if ((type = parse_value(0)) != 0) + if (!emit_seq(parse_set(NULL))) { - if (scantoken == SET_TOKEN) + t_opseq *rseq; + int stackdepth = 0; + idptr = tokenstr; + if ((rseq = parse_value(NULL, RVALUE, &stackdepth))) { - if (!parse_expr()) + if (scantoken == INC_TOKEN || scantoken == DEC_TOKEN) { - parse_error("Bad expression"); + emit_seq(rseq); + emit_unaryop(scantoken); + tokenstr = idptr; + scan_rewind(tokenstr); + emit_seq(parse_value(NULL, LVALUE, NULL)); + } + else if (scantoken != SET_TOKEN) + { + if (stackdepth > 1) + { + rseq = cat_seq(gen_pushexp(NULL), rseq); + rseq = cat_seq(rseq, gen_pullexp(NULL)); + } + else if (stackdepth == 1) + rseq = cat_seq(rseq, gen_drop(NULL)); + emit_seq(rseq); + } + else + { + parse_error("Invalid LVALUE"); return (0); } - if (type & LOCAL_TYPE) - (type & (BYTE_TYPE | BPTR_TYPE)) ? emit_sb() : emit_sw(); - else - (type & (BYTE_TYPE | BPTR_TYPE)) ? emit_sb() : emit_sw(); - } - else if (scantoken == INC_TOKEN || scantoken == DEC_TOKEN) - { - if (type & (BYTE_TYPE | BPTR_TYPE)) - { - emit_dup(); - emit_lb(); - emit_unaryop(scantoken); - emit_sb(); - } - else - { - emit_dup(); - emit_lw(); - emit_unaryop(scantoken); - emit_sw(); - } } else { - if (type & BPTR_TYPE) - emit_lb(); - else if (type & WPTR_TYPE) - emit_lw(); - emit_drop(); + parse_error("Syntax error"); + return (0); } } - else - { - parse_error("Syntax error"); - return (0); - } } if (scan() != EOL_TOKEN && scantoken != COMMENT_TOKEN) { @@ -1327,7 +1236,8 @@ int parse_struc(void) int parse_vars(int type) { long value; - int idlen, size; + int idlen, size, cfnparms; + long cfnvals; char *idstr; switch (scantoken) @@ -1412,20 +1322,77 @@ int parse_vars(int type) type |= PREDEF_TYPE; idstr = tokenstr; idlen = tokenlen; - idfunc_add(tokenstr, tokenlen, type, tag_new(type)); - while (scan() == COMMA_TOKEN) + cfnparms = 0; + cfnvals = 1; // Default to one return value for compatibility + if (scan() == OPEN_PAREN_TOKEN) + { + do + { + if (scan() == ID_TOKEN) + { + cfnparms++; + scan(); + } + } while (scantoken == COMMA_TOKEN); + if (scantoken != CLOSE_PAREN_TOKEN) + { + parse_error("Bad function parameter list"); + return (0); + } + scan(); + } + if (scantoken == POUND_TOKEN) + { + if (!parse_const(&cfnvals)) + { + parse_error("Invalid def return value count"); + return (0); + } + } + type |= funcparms_type(cfnparms) | funcvals_type(cfnvals); + idfunc_add(idstr, idlen, type, tag_new(type)); + while (scantoken == COMMA_TOKEN) { if (scan() == ID_TOKEN) { idstr = tokenstr; idlen = tokenlen; - idfunc_add(tokenstr, tokenlen, type, tag_new(type)); + cfnparms = 0; + cfnvals = 1; // Default to one return value for compatibility + if (scan() == OPEN_PAREN_TOKEN) + { + do + { + if (scan() == ID_TOKEN) + { + cfnparms++; + scan(); + } + } while (scantoken == COMMA_TOKEN); + if (scantoken != CLOSE_PAREN_TOKEN) + { + parse_error("Bad function parameter list"); + return (0); + } + scan(); + } + if (scantoken == POUND_TOKEN) + { + if (!parse_const(&cfnvals)) + { + parse_error("Invalid def return value count"); + return (0); + } + } + type |= funcparms_type(cfnparms) | funcvals_type(cfnvals); + idfunc_add(idstr, idlen, type, tag_new(type)); } else { parse_error("Bad function pre-declaration"); return (0); } + //scan(); } } else @@ -1471,8 +1438,8 @@ int parse_mods(void) } int parse_defs(void) { - char c; - int func_tag, cfnparms, type = GLOBAL_TYPE; + char c, *idstr; + int idlen, func_tag, cfnparms, cfnvals, type = GLOBAL_TYPE, pretype; static char bytecode = 0; if (scantoken == EXPORT_TOKEN) { @@ -1493,29 +1460,15 @@ int parse_defs(void) emit_bytecode_seg(); bytecode = 1; cfnparms = 0; + infuncvals = 1; // Defaut to one return value for compatibility infunc = 1; type |= DEF_TYPE; - if (idglobal_lookup(tokenstr, tokenlen) >= 0) - { - if (!(id_type(tokenstr, tokenlen) & PREDEF_TYPE)) - { - parse_error("Mismatch function type"); - return (0); - } - emit_idfunc(id_tag(tokenstr, tokenlen), PREDEF_TYPE, tokenstr); - func_tag = tag_new(type); - idfunc_set(tokenstr, tokenlen, type, func_tag); // Override any predef type & tag - } - else - { - func_tag = tag_new(type); - idfunc_add(tokenstr, tokenlen, type, func_tag); - } - c = tokenstr[tokenlen]; - tokenstr[tokenlen] = '\0'; - emit_idfunc(func_tag, type, tokenstr); - emit_def(tokenstr, 1); - tokenstr[tokenlen] = c; + idstr = tokenstr; + idlen = tokenlen; + idlocal_reset(); + /* + * Parse parameters and return value count + */ if (scan() == OPEN_PAREN_TOKEN) { do @@ -1534,6 +1487,42 @@ int parse_defs(void) } scan(); } + if (scantoken == POUND_TOKEN) + { + if (!parse_const(&infuncvals)) + { + parse_error("Invalid def return value count"); + return (0); + } + scan(); + } + type |= funcparms_type(cfnparms) | funcvals_type(infuncvals); + if (idglobal_lookup(idstr, idlen) >= 0) + { + pretype = id_type(idstr, idlen); + if (!(pretype & PREDEF_TYPE)) + { + parse_error("Mismatch function type"); + return (0); + } + if ((pretype & FUNC_PARMVALS) != (type & FUNC_PARMVALS)) + parse_warn("Mismatch function params/return values"); + emit_idfunc(id_tag(idstr, idlen), PREDEF_TYPE, idstr, 0); + func_tag = tag_new(type); + idfunc_set(idstr, idlen, type, func_tag); // Override any predef type & tag + } + else + { + func_tag = tag_new(type); + idfunc_add(idstr, idlen, type, func_tag); + } + c = idstr[idlen]; + idstr[idlen] = '\0'; + emit_idfunc(func_tag, type, idstr, 1); + idstr[idlen] = c; + /* + * Parse local vars + */ while (parse_vars(LOCAL_TYPE)) next_line(); emit_enter(cfnparms); prevstmnt = 0; @@ -1551,7 +1540,10 @@ int parse_defs(void) } if (prevstmnt != RETURN_TOKEN) { - emit_const(0); + if (infuncvals) + parse_warn("Inconsistent return value count"); + for (cfnvals = 0; cfnvals < infuncvals; cfnvals++) + emit_const(0); emit_leave(); } return (1); @@ -1569,29 +1561,12 @@ int parse_defs(void) return (0); } cfnparms = 0; + infuncvals = 1; // Defaut to one return value for compatibility infunc = 1; type |= ASM_TYPE; - if (idglobal_lookup(tokenstr, tokenlen) >= 0) - { - if (!(id_type(tokenstr, tokenlen) & PREDEF_TYPE)) - { - parse_error("Mismatch function type"); - return (0); - } - emit_idfunc(id_tag(tokenstr, tokenlen), PREDEF_TYPE, tokenstr); - func_tag = tag_new(type); - idfunc_set(tokenstr, tokenlen, type, func_tag); // Override any predef type & tag - } - else - { - func_tag = tag_new(type); - idfunc_add(tokenstr, tokenlen, type, func_tag); - } - c = tokenstr[tokenlen]; - tokenstr[tokenlen] = '\0'; - emit_idfunc(func_tag, type, tokenstr); - emit_def(tokenstr, 0); - tokenstr[tokenlen] = c; + idstr = tokenstr; + idlen = tokenlen; + idlocal_reset(); if (scan() == OPEN_PAREN_TOKEN) { do @@ -1599,7 +1574,6 @@ int parse_defs(void) if (scan() == ID_TOKEN) { cfnparms++; - idlocal_add(tokenstr, tokenlen, WORD_TYPE, 2); scan(); } } @@ -1611,6 +1585,38 @@ int parse_defs(void) } scan(); } + if (scantoken == POUND_TOKEN) + { + if (!parse_const(&infuncvals)) + { + parse_error("Invalid def return value count"); + return (0); + } + } + type |= funcparms_type(cfnparms) | funcvals_type(infuncvals); + if (idglobal_lookup(idstr, idlen) >= 0) + { + pretype = id_type(idstr, idlen); + if (!(pretype & PREDEF_TYPE)) + { + parse_error("Mismatch function type"); + return (0); + } + if ((pretype & FUNC_PARMVALS) != (type & FUNC_PARMVALS)) + parse_warn("Mismatch function params/return values"); + emit_idfunc(id_tag(idstr, idlen), PREDEF_TYPE, idstr, 0); + func_tag = tag_new(type); + idfunc_set(idstr, idlen, type, func_tag); // Override any predef type & tag + } + else + { + func_tag = tag_new(type); + idfunc_add(idstr, idlen, type, func_tag); + } + c = tokenstr[idlen]; + tokenstr[idlen] = '\0'; + emit_idfunc(func_tag, type, idstr, 0); + idstr[idlen] = c; do { if (scantoken == EOL_TOKEN || scantoken == COMMENT_TOKEN) @@ -1640,7 +1646,8 @@ int parse_module(void) { emit_bytecode_seg(); emit_start(); - emit_def("_INIT", 1); + idlocal_reset(); + emit_idfunc(0, 0, NULL, 1); prevstmnt = 0; while (parse_stmnt()) next_line(); if (scantoken != DONE_TOKEN) diff --git a/src/toolsrc/plasm.c b/src/toolsrc/plasm.c index 2416456..d111694 100755 --- a/src/toolsrc/plasm.c +++ b/src/toolsrc/plasm.c @@ -1,8 +1,7 @@ #include -#include "tokens.h" -#include "lex.h" -#include "codegen.h" -#include "parse.h" +#include "plasm.h" + +int outflags = 0; int main(int argc, char **argv) { @@ -10,23 +9,28 @@ int main(int argc, char **argv) for (i = 1; i < argc; i++) { if (argv[i][0] == '-') - { + { j = 1; while (argv[i][j]) { switch(argv[i][j++]) { case 'A': - flags |= ACME; + outflags |= ACME; break; case 'M': - flags |= MODULE; + outflags |= MODULE; break; + case 'O': + outflags |= OPTIMIZE; + break; + case 'W': + outflags |= WARNINGS; } } } } - emit_flags(flags); + emit_flags(outflags); if (parse_module()) { fprintf(stderr, "Compilation complete.\n"); diff --git a/src/toolsrc/plasm.h b/src/toolsrc/plasm.h new file mode 100755 index 0000000..f3c4432 --- /dev/null +++ b/src/toolsrc/plasm.h @@ -0,0 +1,16 @@ +/* + * Global flags. + */ +#define ACME (1<<0) +#define MODULE (1<<1) +#define OPTIMIZE (1<<2) +#define BYTECODE_SEG (1<<3) +#define INIT (1<<4) +#define SYSFLAGS (1<<5) +#define WARNINGS (1<<6) +extern int outflags; +#include "tokens.h" +#include "lex.h" +#include "symbols.h" +#include "parse.h" +#include "codegen.h" diff --git a/src/toolsrc/symbols.h b/src/toolsrc/symbols.h index 4fd5251..5828901 100755 --- a/src/toolsrc/symbols.h +++ b/src/toolsrc/symbols.h @@ -10,7 +10,7 @@ #define DEF_TYPE (1 << 4) #define BRANCH_TYPE (1 << 5) #define LOCAL_TYPE (1 << 6) -#define EXTERN_TYPE (1 << 7) +#define EXTERN_TYPE (1 << 7) #define ADDR_TYPE (VAR_TYPE | FUNC_TYPE | EXTERN_TYPE) #define WPTR_TYPE (1 << 8) #define BPTR_TYPE (1 << 9) @@ -18,8 +18,16 @@ #define STRING_TYPE (1 << 10) #define TAG_TYPE (1 << 11) #define EXPORT_TYPE (1 << 12) -#define PREDEF_TYPE (1 << 13) +#define PREDEF_TYPE (1 << 13) #define FUNC_TYPE (ASM_TYPE | DEF_TYPE | PREDEF_TYPE) +#define FUNC_PARMS (0x0F << 16) +#define FUNC_VALS (0x0F << 20) +#define FUNC_PARMVALS (FUNC_PARMS|FUNC_VALS) +#define funcparms_type(p) (((p)&0x0F)<<16) +#define funcparms_cnt(t) (((t)>>16)&0x0F) +#define funcvals_type(v) (((v)&0x0F)<<20) +#define funcvals_cnt(t) (((t)>>20)&0x0F) + int id_match(char *name, int len, char *id); int idlocal_lookup(char *name, int len); int idglobal_lookup(char *name, int len); @@ -27,6 +35,7 @@ int idconst_lookup(char *name, int len); int idlocal_add(char *name, int len, int type, int size); int idglobal_add(char *name, int len, int type, int size); int id_add(char *name, int len, int type, int size); +void idlocal_reset(void); int idfunc_set(char *name, int len, int type, int tag); int idfunc_add(char *name, int len, int type, int tag); int idconst_add(char *name, int len, int value); diff --git a/src/vmsrc/a1cmd.pla b/src/vmsrc/a1cmd.pla old mode 100644 new mode 100755 index b2ce603..ed61cb1 --- a/src/vmsrc/a1cmd.pla +++ b/src/vmsrc/a1cmd.pla @@ -39,7 +39,7 @@ predef loadmod, execmod, lookupstrmod // // System variables. // -word version = $0094 // 00.94 +word version = $0099 // 00.99 word systemflags = 0 word heap word symtbl, lastsym @@ -90,18 +90,18 @@ byte execstr[] = "MODEXEC" byte modadrstr[] = "MODADDR" byte argstr[] = "ARGS" word exports[] = @sysstr, @syscall -word = @callstr, @call -word = @putcstr, @cout +word = @callstr, @call +word = @putcstr, @cout word = @putlnstr, @crout -word = @putsstr, @prstr -word = @getcstr, @cin -word = @getsstr, @rdstr -word = @hpmarkstr, @markheap -word = @hpallocstr,@allocheap -word = @hpalignstr,@allocalignheap -word = @hprelstr, @releaseheap -word = @memsetstr, @memset -word = @memcpystr, @memcpy +word = @putsstr, @prstr +word = @getcstr, @cin +word = @getsstr, @rdstr +word = @hpmarkstr, @markheap +word = @hpallocstr,@allocheap +word = @hpalignstr,@allocalignheap +word = @hprelstr, @releaseheap +word = @memsetstr, @memset +word = @memcpystr, @memcpy word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt @@ -112,21 +112,21 @@ word = @modadrstr, @lookupstrmod word = @machidstr, @machid word = @argstr, @cmdptr word = 0 -word syslibsym = @exports +word syslibsym = @exports // // CALL CFFA1 API ENTRYPOINT // SYSCALL(CMD) // asm syscall - LDA ESTKL,X - STX ESP - TAX - JSR $900C - LDX ESP - LDY #$00 - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STX ESP + TAX + JSR $900C + LDX ESP + LDY #$00 + STA ESTKL,X + STY ESTKH,X + RTS end // // CALL 6502 ROUTINE @@ -351,7 +351,7 @@ asm interp STA ESTKH,X RTS end -// +// // A DCI string is one that has the high bit set for every character except the last. // More efficient than C or Pascal strings. // @@ -650,7 +650,7 @@ end def finddirentry(filename) *CFFAFileName = filename perr = syscall($14) - return *CFFAEntryPtr + return *CFFAEntryPtr end def readfile(filename, buffer) *CFFADest = buffer @@ -783,12 +783,12 @@ def loadmod(mod) fin if rdlen > 0 readfile(@filename, heap) - memcpy(@header, heap, 128) - modsize = header:0 - moddep = @header.1 - defofst = modsize + memcpy(@header, heap, 128) + modsize = header:0 + moddep = @header.1 + defofst = modsize init = 0 - if rdlen > 4 and heap=>2 == $DA7E // DAVE = magic number :-) + if rdlen > 4 and heap=>2 == $DA7F // DAVE+1 = magic number :-) // // This is an EXTended RELocatable (data+bytecode) module. // @@ -796,44 +796,46 @@ def loadmod(mod) defcnt = header:8 init = header:10 moddep = @header.12 - // - // Load module dependencies. - // + // + // Load module dependencies. + // while ^moddep if !lookupmod(moddep) if loadmod(moddep) < 0 - return -perr - fin + return -perr + fin fin moddep = moddep + dcitos(moddep, @str) loop - // - // Init def table. - // - deftbl = allocheap(defcnt * 5 + 1) - deflast = deftbl - ^deflast = 0 - // - // Re-read file - // - readfile(@filename, heap) + // + // Init def table. + // + deftbl = allocheap(defcnt * 5 + 1) + deflast = deftbl + ^deflast = 0 + // + // Re-read file + // + readfile(@filename, heap) + else + return -69 fin - // - // Alloc heap space for relocated module (data + bytecode). - // - moddep = moddep + 1 - @header + heap - modfix = moddep - (heap + 2) // Adjust to skip header - modsize = modsize - modfix - rdlen = rdlen - modfix - 2 - modaddr = allocheap(modsize) - memcpy(modaddr, moddep, rdlen) - // - // Add module to symbol table. - // - addmod(mod, modaddr) - // - // Apply all fixups and symbol import/export. - // + // + // Alloc heap space for relocated module (data + bytecode). + // + moddep = moddep + 1 - @header + heap + modfix = moddep - (heap + 2) // Adjust to skip header + modsize = modsize - modfix + rdlen = rdlen - modfix - 2 + modaddr = allocheap(modsize) + memcpy(modaddr, moddep, rdlen) + // + // Add module to symbol table. + // + addmod(mod, modaddr) + // + // Apply all fixups and symbol import/export. + // modfix = modaddr - modfix bytecode = defofst + modfix - MODADDR modend = modaddr + modsize @@ -841,16 +843,16 @@ def loadmod(mod) esd = rld // Extern+Entry Symbol Directory while ^esd // Scan to end of ESD esd = esd + 4 - loop + loop esd = esd + 1 // // Run through the Re-Location Dictionary. // while ^rld if ^rld == $02 - // - // This is a bytcode def entry - add it to the def directory. - // + // + // This is a bytcode def entry - add it to the def directory. + // adddef(rld=>1 - defofst + bytecode, @deflast) else addr = rld=>1 + modfix @@ -880,21 +882,21 @@ def loadmod(mod) fin rld = rld + 4 loop - // + // // Run through the External/Entry Symbol Directory. - // + // while ^esd sym = esd esd = esd + dcitos(esd, @str) if ^esd & $08 - // + // // EXPORT symbol - add it to the global symbol table. - // + // addr = esd=>1 + modfix - MODADDR if uword_isge(addr, bytecode) - // - // Use the def directory address for bytecode. - // + // + // Use the def directory address for bytecode. + // addr = lookupdef(addr - bytecode + bytecode, deftbl) fin addsym(sym, addr) @@ -910,13 +912,13 @@ def loadmod(mod) // fixup = 0 if init - fixup = adddef(init - defofst + bytecode, @deflast)() - if fixup < 0 - perr = -fixup - fin - if !(systemflags & modinitkeep) + fixup = adddef(init - defofst + bytecode, @deflast)() + if fixup < 0 + perr = -fixup + fin + if !(systemflags & modinitkeep) modend = init - defofst + bytecode - fin + fin fin // // Free up the end-of-module in main memory. diff --git a/src/vmsrc/cmd.pla b/src/vmsrc/cmd.pla old mode 100644 new mode 100755 index 8ed47a6..14c9201 --- a/src/vmsrc/cmd.pla +++ b/src/vmsrc/cmd.pla @@ -33,7 +33,7 @@ predef loadmod, execmod, lookupstrmod // // System variable. // -word version = $0094 // 00.94 +word version = $0099 // 00.99 word systemflags = 0 word heap word xheap = $0800 @@ -68,19 +68,19 @@ byte modadrstr = "MODADDR" byte argstr = "ARGS" byte autorun = "AUTORUN" byte prefix[] // overlay with exported symbols table -word exports = @sysstr, @syscall -word = @callstr, @call -word = @putcstr, @cout +word exports = @sysstr, @syscall +word = @callstr, @call +word = @putcstr, @cout word = @putlnstr, @crout -word = @putsstr, @prstr -word = @getcstr, @cin -word = @getsstr, @rdstr -word = @hpmarkstr, @markheap -word = @hpallocstr,@allocheap -word = @hpalignstr,@allocalignheap -word = @hprelstr, @releaseheap -word = @memsetstr, @memset -word = @memcpystr, @memcpy +word = @putsstr, @prstr +word = @getcstr, @cin +word = @getsstr, @rdstr +word = @hpmarkstr, @markheap +word = @hpallocstr,@allocheap +word = @hpalignstr,@allocalignheap +word = @hprelstr, @releaseheap +word = @memsetstr, @memset +word = @memcpystr, @memcpy word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt @@ -101,27 +101,27 @@ word syslibsym = @exports // SYSCALL(CMD, PARAMS) // asm syscall - LDA ESTKL,X - LDY ESTKH,X - STA PARAMS - STY PARAMS+1 - INX - LDA ESTKL,X - STA CMD - JSR $BF00 -CMD: !BYTE 00 -PARAMS: !WORD 0000 - LDY #$00 - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + LDY ESTKH,X + STA PARAMS + STY PARAMS+1 + INX + LDA ESTKL,X + STA CMD + JSR $BF00 +CMD: !BYTE 00 +PARAMS: !WORD 0000 + LDY #$00 + STA ESTKL,X + STY ESTKH,X + RTS end // // CALL 6502 ROUTINE // CALL(ADDR, AREG, XREG, YREG, STATUS) // asm call -REGVALS = SRC +REGVALS = SRC PHP LDA ESTKL+4,X STA TMPL @@ -137,7 +137,7 @@ REGVALS = SRC INX INX INX - INX + INX STX ESP TAX PLA @@ -158,29 +158,29 @@ REGVALS = SRC STY ESTKH,X PLP RTS -JMPTMP JMP (TMP) +JMPTMP JMP (TMP) end // // CALL LOADED SYSTEM PROGRAM // asm exec - LDX #$00 - STX IFPL - LDA #$BF - STA IFPH - LDX #$FE - TXS - LDX #ESTKSZ/2 - BIT ROMEN - JMP $2000 + LDX #$00 + STX IFPL + LDA #$BF + STA IFPH + LDX #$FE + TXS + LDX #ESTKSZ/2 + BIT ROMEN + JMP $2000 end // // EXIT // asm reboot - BIT ROMEN - DEC $03F4 ; INVALIDATE POWER-UP BYTE - JMP ($FFFC) ; RESET + BIT ROMEN + DEC $03F4 ; INVALIDATE POWER-UP BYTE + JMP ($FFFC) ; RESET end // // SET MEMORY TO VALUE @@ -188,111 +188,111 @@ end // With optimizations from Peter Ferrie // asm memset - LDA ESTKL+2,X - STA DSTL - LDA ESTKH+2,X - STA DSTH - LDY ESTKL,X - BEQ + - INC ESTKH,X - LDY #$00 -+ LDA ESTKH,X - BEQ SETMEX -SETMLPL CLC - LDA ESTKL+1,X -SETMLPH STA (DST),Y - DEC ESTKL,X - BEQ ++ -- INY - BEQ + --- BCS SETMLPL - SEC - LDA ESTKH+1,X - BCS SETMLPH -+ INC DSTH - BNE -- -++ DEC ESTKH,X - BNE - -SETMEX INX - INX - RTS + LDA ESTKL+2,X + STA DSTL + LDA ESTKH+2,X + STA DSTH + LDY ESTKL,X + BEQ + + INC ESTKH,X + LDY #$00 ++ LDA ESTKH,X + BEQ SETMEX +SETMLPL CLC + LDA ESTKL+1,X +SETMLPH STA (DST),Y + DEC ESTKL,X + BEQ ++ +- INY + BEQ + +-- BCS SETMLPL + SEC + LDA ESTKH+1,X + BCS SETMLPH ++ INC DSTH + BNE -- +++ DEC ESTKH,X + BNE - +SETMEX INX + INX + RTS end // // COPY MEMORY // MEMCPY(DSTADDR, SRCADDR, SIZE) // asm memcpy - INX - INX - LDA ESTKL-2,X - ORA ESTKH-2,X - BEQ CPYMEX - LDA ESTKL-1,X - CMP ESTKL,X - LDA ESTKH-1,X - SBC ESTKH,X - BCC REVCPY + INX + INX + LDA ESTKL-2,X + ORA ESTKH-2,X + BEQ CPYMEX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BCC REVCPY ; ; FORWARD COPY ; - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL-1,X - STA SRCL - LDA ESTKH-1,X - STA SRCH - LDY ESTKL-2,X - BEQ FORCPYLP - INC ESTKH-2,X - LDY #$00 -FORCPYLP LDA (SRC),Y - STA (DST),Y - INY - BNE + - INC DSTH - INC SRCH -+ DEC ESTKL-2,X - BNE FORCPYLP - DEC ESTKH-2,X - BNE FORCPYLP - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL-1,X + STA SRCL + LDA ESTKH-1,X + STA SRCH + LDY ESTKL-2,X + BEQ FORCPYLP + INC ESTKH-2,X + LDY #$00 +FORCPYLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL-2,X + BNE FORCPYLP + DEC ESTKH-2,X + BNE FORCPYLP + RTS ; ; REVERSE COPY ; -REVCPY ;CLC - LDA ESTKL-2,X - ADC ESTKL,X - STA DSTL - LDA ESTKH-2,X - ADC ESTKH,X - STA DSTH - CLC - LDA ESTKL-2,X - ADC ESTKL-1,X - STA SRCL - LDA ESTKH-2,X - ADC ESTKH-1,X - STA SRCH - DEC DSTH - DEC SRCH - LDY #$FF - LDA ESTKL-2,X - BEQ REVCPYLP - INC ESTKH-2,X -REVCPYLP LDA (SRC),Y - STA (DST),Y - DEY - CPY #$FF - BNE + - DEC DSTH - DEC SRCH -+ DEC ESTKL-2,X - BNE REVCPYLP - DEC ESTKH-2,X - BNE REVCPYLP -CPYMEX RTS +REVCPY ;CLC + LDA ESTKL-2,X + ADC ESTKL,X + STA DSTL + LDA ESTKH-2,X + ADC ESTKH,X + STA DSTH + CLC + LDA ESTKL-2,X + ADC ESTKL-1,X + STA SRCL + LDA ESTKH-2,X + ADC ESTKH-1,X + STA SRCH + DEC DSTH + DEC SRCH + LDY #$FF + LDA ESTKL-2,X + BEQ REVCPYLP + INC ESTKH-2,X +REVCPYLP LDA (SRC),Y + STA (DST),Y + DEY + CPY #$FF + BNE + + DEC DSTH + DEC SRCH ++ DEC ESTKL-2,X + BNE REVCPYLP + DEC ESTKH-2,X + BNE REVCPYLP +CPYMEX RTS end // // COPY FROM MAIN MEM TO AUX MEM. @@ -300,191 +300,191 @@ end // MEMXCPY(DST, SRC, SIZE) // asm memxcpy - LDA ESTKL+1,X - STA $3C - CLC - ADC ESTKL,X - STA $3E - LDA ESTKH+1,X - STA $3D - ADC ESTKH,X - STA $3F - LDA ESTKL+2,X - STA $42 - LDA ESTKH+2,X - STA $43 - STX ESP - BIT ROMEN - SEC - JSR $C311 - BIT LCRDEN+LCBNK2 - LDX ESP - INX - INX - RTS + LDA ESTKL+1,X + STA $3C + CLC + ADC ESTKL,X + STA $3E + LDA ESTKH+1,X + STA $3D + ADC ESTKH,X + STA $3F + LDA ESTKL+2,X + STA $42 + LDA ESTKH+2,X + STA $43 + STX ESP + BIT ROMEN + SEC + JSR $C311 + BIT LCRDEN+LCBNK2 + LDX ESP + INX + INX + RTS end asm crout - DEX - LDA #$0D - BNE + - ; FALL THROUGH TO COUT + DEX + LDA #$0D + BNE + + ; FALL THROUGH TO COUT end // // CHAR OUT // COUT(CHAR) // asm cout - LDA ESTKL,X - BIT $BF98 - BMI + - JSR TOUPR -+ ORA #$80 - BIT ROMEN - JSR $FDED - BIT LCRDEN+LCBNK2 - RTS + LDA ESTKL,X + BIT $BF98 + BMI + + JSR TOUPR ++ ORA #$80 + BIT ROMEN + JSR $FDED + BIT LCRDEN+LCBNK2 + RTS end // // CHAR IN // RDKEY() // asm cin - BIT ROMEN - JSR $FD0C - BIT LCRDEN+LCBNK2 - DEX - LDY #$00 - AND #$7F - STA ESTKL,X - STY ESTKH,X - RTS + BIT ROMEN + JSR $FD0C + BIT LCRDEN+LCBNK2 + DEX + LDY #$00 + AND #$7F + STA ESTKL,X + STY ESTKH,X + RTS end // // PRINT STRING // PRSTR(STR) // asm prstr - LDY #$00 - LDA ESTKL,X - STA SRCL - LDA ESTKH,X - STA SRCH - LDA (SRC),Y - BEQ ++ - STA TMP - BIT ROMEN -- INY - LDA (SRC),Y - BIT $BF98 - BMI + - JSR TOUPR -+ ORA #$80 - JSR $FDED - CPY TMP - BNE - - BIT LCRDEN+LCBNK2 -++ RTS + LDY #$00 + LDA ESTKL,X + STA SRCL + LDA ESTKH,X + STA SRCH + LDA (SRC),Y + BEQ ++ + STA TMP + BIT ROMEN +- INY + LDA (SRC),Y + BIT $BF98 + BMI + + JSR TOUPR ++ ORA #$80 + JSR $FDED + CPY TMP + BNE - + BIT LCRDEN+LCBNK2 +++ RTS end // // PRINT BYTE // asm prbyte - LDA ESTKL,X - STX ESP - BIT ROMEN - JSR $FDDA - LDX ESP - BIT LCRDEN+LCBNK2 - RTS + LDA ESTKL,X + STX ESP + BIT ROMEN + JSR $FDDA + LDX ESP + BIT LCRDEN+LCBNK2 + RTS end // // PRINT WORD // asm prword - STX ESP - TXA - TAY - LDA ESTKH,Y - LDX ESTKL,Y - BIT ROMEN - JSR $F941 - LDX ESP - BIT LCRDEN+LCBNK2 - RTS + STX ESP + TXA + TAY + LDA ESTKH,Y + LDX ESTKL,Y + BIT ROMEN + JSR $F941 + LDX ESP + BIT LCRDEN+LCBNK2 + RTS end // // READ STRING // STR = RDSTR(PROMPTCHAR) // asm rdstr - LDA ESTKL,X - STA $33 - STX ESP - BIT ROMEN - JSR $FD6A - STX $01FF -- LDA $01FF,X - AND #$7F - STA $01FF,X - DEX - BPL - - TXA - LDX ESP - STA ESTKL,X - LDA #$01 - STA ESTKH,X - BIT LCRDEN+LCBNK2 - RTS + LDA ESTKL,X + STA $33 + STX ESP + BIT ROMEN + JSR $FD6A + STX $01FF +- LDA $01FF,X + AND #$7F + STA $01FF,X + DEX + BPL - + TXA + LDX ESP + STA ESTKL,X + LDA #$01 + STA ESTKH,X + BIT LCRDEN+LCBNK2 + RTS end asm uword_isge - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isle - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - EOR #$FF - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_isgt - LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end asm uword_islt - LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - LDA #$FF - ADC #$00 - STA ESTKL+1,X - STA ESTKH+1,X - INX - RTS + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS end // // Utility routines. @@ -504,28 +504,28 @@ end // return len //end asm dcitos - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDY #$00 -- LDA (SRC),Y - CMP #$80 - AND #$7F - INY - STA (DST),Y - BCS - - TYA - LDY #$00 - STA (DST),Y - INX - STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDY #$00 +- LDA (SRC),Y + CMP #$80 + AND #$7F + INY + STA (DST),Y + BCS - + TYA + LDY #$00 + STA (DST),Y + INX + STA ESTKL,X + STY ESTKH,X + RTS end //def stodci(str, dci) // byte len, c @@ -537,50 +537,50 @@ end // len = len - 1 // (dci).[len] = c // while len -// c = toupper((str).[len]) | $80 -// len = len - 1 -// (dci).[len] = c +// c = toupper((str).[len]) | $80 +// len = len - 1 +// (dci).[len] = c // loop // return ^str //end asm stodci - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - INX - LDY #$00 - LDA (SRC),Y - BEQ ++ - TAY - LDA (SRC),Y - JSR TOUPR - BNE + -- LDA (SRC),Y - JSR TOUPR - ORA #$80 -+ DEY - STA (DST),Y - BNE - - LDA (SRC),Y -++ STA ESTKL,X - STY ESTKH,X - RTS + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + INX + LDY #$00 + LDA (SRC),Y + BEQ ++ + TAY + LDA (SRC),Y + JSR TOUPR + BNE + +- LDA (SRC),Y + JSR TOUPR + ORA #$80 ++ DEY + STA (DST),Y + BNE - + LDA (SRC),Y +++ STA ESTKL,X + STY ESTKH,X + RTS end asm toupper - LDA ESTKL,X -TOUPR AND #$7F - CMP #'a' - BCC + - CMP #'z'+1 - BCS + - SBC #$1F -+ STA ESTKL,X - RTS + LDA ESTKL,X +TOUPR AND #$7F + CMP #'a' + BCC + + CMP #'z'+1 + BCS + + SBC #$1F ++ STA ESTKL,X + RTS end // // Module symbols are entered into the symbol table @@ -599,25 +599,25 @@ end // return dci //end asm modtosym - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDA ESTKL,X - STA ESTKL+1,X - STA DSTL - LDA ESTKH,X - STA ESTKH+1,X - STA DSTH - INX - LDY #$00 - LDA #'#'+$80 -- STA (DST),Y - ASL - LDA (SRC),Y - INY - BCS - - RTS + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDA ESTKL,X + STA ESTKL+1,X + STA DSTL + LDA ESTKH,X + STA ESTKH+1,X + STA DSTH + INX + LDY #$00 + LDA #'#'+$80 +- STA (DST),Y + ASL + LDA (SRC),Y + INY + BCS - + RTS end // // Lookup routines. @@ -640,46 +640,46 @@ end // loop // return 0 asm lookuptbl - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDY #$00 -- LDA (DST),Y - BEQ + - CMP (SRC),Y - BNE ++ - INY - ASL - BCS - - LDA (DST),Y - PHA - INY - LDA (DST),Y - TAY - PLA -+ INX - STA ESTKL,X - STY ESTKH,X - RTS -++ LDY #$00 --- LDA (DST),Y - INC DSTL - BEQ + ---- ASL - BCS -- - LDA #$02 - ADC DSTL - STA DSTL - BCC - - INC DSTH - BCS - -+ INC DSTH - BNE --- + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDY #$00 +- LDA (DST),Y + BEQ + + CMP (SRC),Y + BNE ++ + INY + ASL + BCS - + LDA (DST),Y + PHA + INY + LDA (DST),Y + TAY + PLA ++ INX + STA ESTKL,X + STY ESTKH,X + RTS +++ LDY #$00 +-- LDA (DST),Y + INC DSTL + BEQ + +--- ASL + BCS -- + LDA #$02 + ADC DSTL + STA DSTL + BCC - + INC DSTH + BCS - ++ INC DSTH + BNE --- end // // ProDOS routines @@ -743,15 +743,15 @@ def allocheap(size) heap = heap + size if systemflags & reshgr1 if uword_islt(addr, $4000) and uword_isgt(heap, $2000) - addr = $4000 - heap = addr + size - fin + addr = $4000 + heap = addr + size + fin fin if systemflags & reshgr2 if uword_islt(addr, $6000) and uword_isgt(heap, $4000) - addr = $6000 - heap = addr + size - fin + addr = $6000 + heap = addr + size + fin fin if uword_isge(heap, @addr) return 0 @@ -784,27 +784,27 @@ def allocxheap(size) xheap = xheap + size if systemflags & restxt1 if uword_isle(xaddr, $0800) and uword_isgt(xheap, $0400) - xaddr = $0800 - xheap = xaddr + size - fin + xaddr = $0800 + xheap = xaddr + size + fin fin if systemflags & restxt2 if uword_isle(xaddr, $0C00) and uword_isgt(xheap, $0800) - xaddr = $0C00 - xheap = xaddr + size - fin + xaddr = $0C00 + xheap = xaddr + size + fin fin if systemflags & resxhgr1 if uword_isle(xaddr, $4000) and uword_isgt(xheap, $2000) - xaddr = $4000 - xheap = xaddr + size - fin + xaddr = $4000 + xheap = xaddr + size + fin fin if systemflags & resxhgr2 if uword_isle(xaddr, $6000) and uword_isgt(xheap, $4000) - xaddr = $6000 - xheap = xaddr + size - fin + xaddr = $6000 + xheap = xaddr + size + fin fin if uword_isge(xheap, $BF00) return 0 @@ -852,12 +852,12 @@ def lookupextern(esd, index) esd = esd + dcitos(esd, @str) if esd->0 & $10 and esd->1 == index addr = lookupsym(sym) - if !addr + if !addr perr = $81 - cout('?') - prstr(@str) - crout - fin + cout('?') + prstr(@str) + crout + fin return addr fin esd = esd + 3 @@ -901,71 +901,73 @@ def loadmod(mod) refnum = open(@filename, iobuffer) if refnum > 0 rdlen = read(refnum, @header, 128) - modsize = header:0 - moddep = @header.1 - defofst = modsize + modsize = header:0 + moddep = @header.1 + defofst = modsize init = 0 - if rdlen > 4 and header:2 == $DA7E // DAVE = magic number :-) + if rdlen > 4 and header:2 == $DA7F // DAVE+1 = magic number :-) // // This is an EXTended RELocatable (data+bytecode) module. // - systemflags = header:4 | systemflags + systemflags = header:4 | systemflags defofst = header:6 defcnt = header:8 init = header:10 moddep = @header.12 - // - // Load module dependencies. - // + // + // Load module dependencies. + // while ^moddep if !lookupmod(moddep) - close(refnum) - refnum = 0 + close(refnum) + refnum = 0 if loadmod(moddep) < 0 - return -perr - fin + return -perr + fin fin moddep = moddep + dcitos(moddep, @str) loop - // - // Init def table. - // - deftbl = allocheap(defcnt * 5 + 1) - deflast = deftbl - ^deflast = 0 - if !refnum - // - // Reset read pointer. - // - refnum = open(@filename, iobuffer) - rdlen = read(refnum, @header, 128) - fin + // + // Init def table. + // + deftbl = allocheap(defcnt * 5 + 1) + deflast = deftbl + ^deflast = 0 + if !refnum + // + // Reset read pointer. + // + refnum = open(@filename, iobuffer) + rdlen = read(refnum, @header, 128) + fin + else + return -69 fin - // - // Alloc heap space for relocated module (data + bytecode). - // - moddep = moddep + 1 - modfix = moddep - @header.2 // Adjust to skip header - modsize = modsize - modfix - rdlen = rdlen - modfix - 2 - modaddr = allocheap(modsize) - memcpy(modaddr, moddep, rdlen) - // - // Read in remainder of module into memory for fixups. - // - addr = modaddr// + // + // Alloc heap space for relocated module (data + bytecode). + // + moddep = moddep + 1 + modfix = moddep - @header.2 // Adjust to skip header + modsize = modsize - modfix + rdlen = rdlen - modfix - 2 + modaddr = allocheap(modsize) + memcpy(modaddr, moddep, rdlen) + // + // Read in remainder of module into memory for fixups. + // + addr = modaddr// repeat addr = addr + rdlen rdlen = read(refnum, addr, 4096) until rdlen <= 0 close(refnum) - // - // Add module to symbol table. - // - addmod(mod, modaddr) - // - // Apply all fixups and symbol import/export. - // + // + // Add module to symbol table. + // + addmod(mod, modaddr) + // + // Apply all fixups and symbol import/export. + // modfix = modaddr - modfix bytecode = defofst + modfix - MODADDR modend = modaddr + modsize @@ -973,39 +975,39 @@ def loadmod(mod) esd = rld // Extern+Entry Symbol Directory while ^esd // Scan to end of ESD esd = esd + 4 - loop + loop esd = esd + 1 - // - // Locate bytecode defs in appropriate bank. - // - if ^MACHID & $30 == $30 - defbank = 1 - defaddr = allocxheap(rld - bytecode) - modend = bytecode - else - defbank = 0 - defaddr = bytecode - fin + // + // Locate bytecode defs in appropriate bank. + // + if ^MACHID & $30 == $30 + defbank = 1 + defaddr = allocxheap(rld - bytecode) + modend = bytecode + else + defbank = 0 + defaddr = bytecode + fin // // Run through the Re-Location Dictionary. // while ^rld if ^rld == $02 - // - // This is a bytcode def entry - add it to the def directory. - // - adddef(defbank, rld=>1 - defofst + defaddr, @deflast) + // + // This is a bytcode def entry - add it to the def directory. + // + adddef(defbank, rld=>1 - defofst + defaddr, @deflast) else addr = rld=>1 + modfix if uword_isge(addr, modaddr) // Skip fixups to header if ^rld & $80 // WORD sized fixup. fixup = *addr - else // BYTE sized fixup. + else // BYTE sized fixup. fixup = ^addr fin if ^rld & $10 // EXTERN reference. fixup = fixup + lookupextern(esd, rld->3) - else // INTERN fixup. + else // INTERN fixup. fixup = fixup + modfix - MODADDR if uword_isge(fixup, bytecode) // @@ -1016,40 +1018,40 @@ def loadmod(mod) fin if ^rld & $80 // WORD sized fixup. *addr = fixup - else // BYTE sized fixup. + else // BYTE sized fixup. ^addr = fixup fin fin fin rld = rld + 4 loop - // + // // Run through the External/Entry Symbol Directory. - // + // while ^esd sym = esd esd = esd + dcitos(esd, @str) if ^esd & $08 - // + // // EXPORT symbol - add it to the global symbol table. - // + // addr = esd=>1 + modfix - MODADDR if uword_isge(addr, bytecode) - // - // Use the def directory address for bytecode. - // + // + // Use the def directory address for bytecode. + // addr = lookupdef(addr - bytecode + defaddr, deftbl) fin addsym(sym, addr) fin esd = esd + 3 loop - if defbank - // - // Move bytecode to AUX bank. - // - memxcpy(defaddr, bytecode, modsize - (bytecode - modaddr)) - fin + if defbank + // + // Move bytecode to AUX bank. + // + memxcpy(defaddr, bytecode, modsize - (bytecode - modaddr)) + fin fin if perr return -perr @@ -1060,21 +1062,21 @@ def loadmod(mod) fixup = 0 // This is repurposed for the return code if init fixup = adddef(defbank, init - defofst + defaddr, @deflast)() - if fixup < modinitkeep - // - // Free init routine unless initkeep - // - if defbank - xheap = init - defofst + defaddr - else - modend = init - defofst + defaddr - fin - if fixup < 0 + if fixup < modinitkeep + // + // Free init routine unless initkeep + // + if defbank + xheap = init - defofst + defaddr + else + modend = init - defofst + defaddr + fin + if fixup < 0 perr = -fixup - fin - else - fixup = fixup & ~modinitkeep - fin + fin + else + fixup = fixup & ~modinitkeep + fin fin // // Free up the end-of-module in main memory. @@ -1097,12 +1099,12 @@ def volumes strbuf = databuff for i = 0 to 15 ^strbuf = ^strbuf & $0F - if ^strbuf - cout('/') - prstr(strbuf) - crout() - fin - strbuf = strbuf + 16 + if ^strbuf + cout('/') + prstr(strbuf) + crout() + fin + strbuf = strbuf + 16 next end def catalog(optpath) @@ -1143,12 +1145,12 @@ def catalog(optpath) if type & $F0 == $D0 // Is it a directory? cout('/') len = len + 1 - elsif entry->$10 == $FF - cout('-') - len = len + 1 - elsif entry->$10 == $FE - cout('+') - len = len + 1 + elsif entry->$10 == $FF + cout('-') + len = len + 1 + elsif entry->$10 == $FE + cout('+') + len = len + 1 fin for len = 19 - len downto 0 cout(' ') @@ -1187,9 +1189,9 @@ def striptrail(strptr) for i = 1 to ^strptr if ^(strptr + i) <= ' ' - ^strptr = i - 1 - return strptr - fin + ^strptr = i - 1 + return strptr + fin next return strptr end @@ -1225,23 +1227,23 @@ def execsys(sysfile) if ^sysfile memcpy($280, sysfile, ^sysfile + 1) - striptrail(sysfile) - refnum = open(sysfile, iobuffer) - if refnum - len = read(refnum, databuff, $FFFF) - resetmemfiles() - if len - memcpy(sysfile, $280, ^$280 + 1) - if stripchars(sysfile) and ^$2000 == $4C and *$2003 == $EEEE - stripspaces(sysfile) - if ^$2005 >= ^sysfile + 1 - memcpy($2006, sysfile, ^sysfile + 1) - fin - fin - striptrail($280) - exec() - fin - fin + striptrail(sysfile) + refnum = open(sysfile, iobuffer) + if refnum + len = read(refnum, databuff, $FFFF) + resetmemfiles() + if len + memcpy(sysfile, $280, ^$280 + 1) + if stripchars(sysfile) and ^$2000 == $4C and *$2003 == $EEEE + stripspaces(sysfile) + if ^$2005 >= ^sysfile + 1 + memcpy($2006, sysfile, ^sysfile + 1) + fin + fin + striptrail($280) + exec() + fin + fin fin end def execmod(modfile) @@ -1251,16 +1253,16 @@ def execmod(modfile) perr = 1 if stodci(modfile, @moddci) saveheap = heap - savexheap = xheap - savesym = lastsym - saveflags = systemflags - if loadmod(@moddci) < modkeep - lastsym = savesym - xheap = savexheap - heap = saveheap - fin - ^lastsym = 0 - systemflags = saveflags + savexheap = xheap + savesym = lastsym + saveflags = systemflags + if loadmod(@moddci) < modkeep + lastsym = savesym + xheap = savexheap + heap = saveheap + fin + ^lastsym = 0 + systemflags = saveflags fin return -perr end @@ -1303,34 +1305,34 @@ while 1 if cmdln when toupper(parsecmd(@cmdln)) is 'Q' - reboot() - break - is 'C' - catalog(@cmdln) - break - is 'P' - setpfx(@cmdln) - break - is 'V' - volumes() - break - is '-' - execsys(@cmdln) - break - is '+' - execmod(striptrail(@cmdln)) - break - otherwise - cout('?') + reboot() + break + is 'C' + catalog(@cmdln) + break + is 'P' + setpfx(@cmdln) + break + is 'V' + volumes() + break + is '-' + execsys(@cmdln) + break + is '+' + execmod(striptrail(@cmdln)) + break + otherwise + cout('?') wend if perr prstr("ERR:$") - prbyte(perr) - perr = 0 + prbyte(perr) + perr = 0 else prstr("OK") fin - crout() + crout() fin prstr(getpfx(@prefix)) memcpy(@cmdln, rdstr($BA), 128) diff --git a/src/vmsrc/plvm.c b/src/vmsrc/plvm.c index fbeb538..f05e305 100755 --- a/src/vmsrc/plvm.c +++ b/src/vmsrc/plvm.c @@ -17,32 +17,32 @@ int show_state = 0; /* * Bytecode memory */ -#define BYTE_PTR(bp) ((byte)((bp)[0])) -#define WORD_PTR(bp) ((word)((bp)[0] | ((bp)[1] << 8))) -#define UWORD_PTR(bp) ((uword)((bp)[0] | ((bp)[1] << 8))) -#define TO_UWORD(w) ((uword)((w))) -#define MOD_ADDR 0x1000 -#define DEF_CALL 0x0800 -#define DEF_CALLSZ 0x0800 -#define DEF_ENTRYSZ 6 -#define MEM_SIZE 65536 +#define BYTE_PTR(bp) ((byte)((bp)[0])) +#define WORD_PTR(bp) ((word)((bp)[0] | ((bp)[1] << 8))) +#define UWORD_PTR(bp) ((uword)((bp)[0] | ((bp)[1] << 8))) +#define TO_UWORD(w) ((uword)((w))) +#define MOD_ADDR 0x1000 +#define DEF_CALL 0x0800 +#define DEF_CALLSZ 0x0800 +#define DEF_ENTRYSZ 6 +#define MEM_SIZE 65536 byte mem_data[MEM_SIZE]; uword sp = 0x01FE, fp = 0xFFFF, heap = 0x0200, deftbl = DEF_CALL, lastdef = DEF_CALL; -#define PHA(b) (mem_data[sp--]=(b)) -#define PLA() (mem_data[++sp]) -#define EVAL_STACKSZ 16 -#define PUSH(v) (*(--esp))=(v) -#define POP ((word)(*(esp++))) -#define UPOP ((uword)(*(esp++))) -#define TOS (esp[0]) +#define PHA(b) (mem_data[sp--]=(b)) +#define PLA (mem_data[++sp]) +#define EVAL_STACKSZ 16 +#define PUSH(v) (*(--esp))=(v) +#define POP ((word)(*(esp++))) +#define UPOP ((uword)(*(esp++))) +#define TOS (esp[0]) word eval_stack[EVAL_STACKSZ]; word *esp = eval_stack + EVAL_STACKSZ; -#define SYMTBLSZ 1024 -#define SYMSZ 16 -#define MODTBLSZ 128 -#define MODSZ 16 -#define MODLSTSZ 32 +#define SYMTBLSZ 1024 +#define SYMSZ 16 +#define MODTBLSZ 128 +#define MODSZ 16 +#define MODLSTSZ 32 byte symtbl[SYMTBLSZ]; byte *lastsym = symtbl; byte modtbl[MODTBLSZ]; @@ -53,7 +53,7 @@ byte *lastmod = modtbl; void interp(code *ip); /* * Utility routines. - * + * * A DCI string is one that has the high bit set for every character except the last. * More efficient than C or Pascal strings. */ @@ -126,7 +126,7 @@ void dump_tbl(byte *tbl) putchar(':'); while (len++ < 15) putchar(' '); - printf("$%04X\n", tbl[0] | (tbl[1] << 8)); + printf("$%04X\n", tbl[0] | (tbl[1] << 8)); tbl += 2; } } @@ -248,7 +248,7 @@ int load_mod(byte *mod) moddep = header + 1; modsize = header[0] | (header[1] << 8); magic = header[2] | (header[3] << 8); - if (magic == 0xDA7E) + if (magic == 0xDA7F) { /* * This is a relocatable bytecode module. @@ -282,7 +282,7 @@ int load_mod(byte *mod) } /* * Alloc heap space for relocated module (data + bytecode). - */ + */ moddep += 1; hdrlen = moddep - header; len -= hdrlen; @@ -381,7 +381,7 @@ int load_mod(byte *mod) { if (show_state) printf("BYTE"); mem_data[addr] = fixup; - } + } } else { @@ -502,18 +502,18 @@ void call(uword pc) exit(1); } } - + /* * OPCODE TABLE * -OPTBL: DW ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E - DW NEG,COMP,AND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E - DW NOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E - DW DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E - DW ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E - DW BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,??? ; 50 52 54 56 58 5A 5C 5E - DW LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E - DW SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E +OPTBL: DW ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E + DW NEG,COMP,AND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E + DW NOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E + DW DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + DW ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E + DW BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,??? ; 50 52 54 56 58 5A 5C 5E + DW LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E + DW SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E */ void interp(code *ip) { @@ -533,9 +533,9 @@ void interp(code *ip) } switch (*ip++) { - /* - * 0x00-0x0F - */ + /* + * 0x00-0x0F + */ case 0x00: // ZERO : TOS = 0 PUSH(0); break; @@ -656,13 +656,11 @@ void interp(code *ip) PUSH(val); break; case 0x34: // PUSH : TOSP = TOS - val = POP; - PHA(val >> 8); + val = esp - eval_stack; PHA(val); break; case 0x36: // PULL : TOS = TOSP - PUSH(mem_data[sp] | (mem_data[sp + 1] << 8)); - sp += 2; + esp = eval_stack + PLA; break; case 0x38: // BRGT : TOS-1 > TOS ? IP += (IP) val = POP; @@ -775,7 +773,7 @@ void interp(code *ip) printf("\n"); break; case 0x5A: // LEAVE : DEL FRAME, IP = TOFP - fp += PLA(); + fp += PLA; case 0x5C: // RET : IP = TOFP return; case 0x5E: // ??? @@ -822,14 +820,14 @@ void interp(code *ip) /* * 0x70-0x7F */ - case 0x70: // SB : BYTE (TOS) = TOS-1 - val = POP; + case 0x70: // SB : BYTE (TOS-1) = TOS ea = UPOP; + val = POP; mem_data[ea] = val; break; - case 0x72: // SW : WORD (TOS) = TOS-1 - val = POP; + case 0x72: // SW : WORD (TOS-1) = TOS ea = UPOP; + val = POP; mem_data[ea] = val; mem_data[ea + 1] = val >> 8; break; @@ -889,7 +887,7 @@ int main(int argc, char **argv) { byte dci[32]; int i; - + if (--argc) { argv++; diff --git a/src/vmsrc/plvm01.s b/src/vmsrc/plvm01.s index dcd4f12..787c59c 100644 --- a/src/vmsrc/plvm01.s +++ b/src/vmsrc/plvm01.s @@ -8,928 +8,921 @@ ;* ;* VM ZERO PAGE LOCATIONS ;* - !SOURCE "vmsrc/plvmzp.inc" + !SOURCE "vmsrc/plvmzp.inc" ;* ;* INTERPRETER INSTRUCTION POINTER INCREMENT MACRO ;* - !MACRO INC_IP { - INY - BNE *+4 - INC IPH - } + !MACRO INC_IP { + INY + BNE *+4 + INC IPH + } ;* ;* INTERPRETER HEADER+INITIALIZATION ;* - *= $0280 -SEGBEGIN JMP VMINIT + *= $0280 +SEGBEGIN JMP VMINIT ;* ;* SYSTEM INTERPRETER ENTRYPOINT ;* -INTERP PLA - CLC - ADC #$01 +INTERP PLA + CLC + ADC #$01 STA IPL PLA - ADC #$00 + ADC #$00 STA IPH - LDY #$00 - JMP FETCHOP + LDY #$00 + JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER ;* -IINTERP PLA +IINTERP PLA STA TMPL PLA STA TMPH - LDY #$02 - LDA (TMP),Y - STA IPH - DEY - LDA (TMP),Y - STA IPL + LDY #$02 + LDA (TMP),Y + STA IPH + DEY + LDA (TMP),Y + STA IPL DEY - JMP FETCHOP + JMP FETCHOP ;* ;* MUL TOS-1 BY TOS ;* -MUL STY IPY - LDY #$10 - LDA ESTKL+1,X - EOR #$FF - STA TMPL - LDA ESTKH+1,X - EOR #$FF - STA TMPH - LDA #$00 - STA ESTKL+1,X ; PRODL -; STA ESTKH+1,X ; PRODH -MULLP LSR TMPH ; MULTPLRH - ROR TMPL ; MULTPLRL - BCS + - STA ESTKH+1,X ; PRODH - LDA ESTKL,X ; MULTPLNDL - ADC ESTKL+1,X ; PRODL - STA ESTKL+1,X - LDA ESTKH,X ; MULTPLNDH - ADC ESTKH+1,X ; PRODH -+ ASL ESTKL,X ; MULTPLNDL - ROL ESTKH,X ; MULTPLNDH - DEY - BNE MULLP - STA ESTKH+1,X ; PRODH - LDY IPY -; INX -; JMP NEXTOP - JMP DROP +MUL STY IPY + LDY #$10 + LDA ESTKL+1,X + EOR #$FF + STA TMPL + LDA ESTKH+1,X + EOR #$FF + STA TMPH + LDA #$00 + STA ESTKL+1,X ; PRODL +; STA ESTKH+1,X ; PRODH +MULLP LSR TMPH ; MULTPLRH + ROR TMPL ; MULTPLRL + BCS + + STA ESTKH+1,X ; PRODH + LDA ESTKL,X ; MULTPLNDL + ADC ESTKL+1,X ; PRODL + STA ESTKL+1,X + LDA ESTKH,X ; MULTPLNDH + ADC ESTKH+1,X ; PRODH ++ ASL ESTKL,X ; MULTPLNDL + ROL ESTKH,X ; MULTPLNDH + DEY + BNE MULLP + STA ESTKH+1,X ; PRODH + LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCREMENT TOS ;* -INCR INC ESTKL,X - BNE INCR1 - INC ESTKH,X -INCR1 JMP NEXTOP +INCR INC ESTKL,X + BNE INCR1 + INC ESTKH,X +INCR1 JMP NEXTOP ;* ;* DECREMENT TOS ;* -DECR LDA ESTKL,X - BNE DECR1 - DEC ESTKH,X -DECR1 DEC ESTKL,X - JMP NEXTOP +DECR LDA ESTKL,X + BNE DECR1 + DEC ESTKH,X +DECR1 DEC ESTKL,X + JMP NEXTOP ;* ;* BITWISE COMPLIMENT TOS ;* -COMP LDA #$FF - EOR ESTKL,X - STA ESTKL,X - LDA #$FF - EOR ESTKH,X - STA ESTKH,X - JMP NEXTOP +COMP LDA #$FF + EOR ESTKL,X + STA ESTKL,X + LDA #$FF + EOR ESTKH,X + STA ESTKH,X + JMP NEXTOP ;* ;* OPCODE TABLE ;* - !ALIGN 255,0 -OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E - !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E - !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E - !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E - !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E - !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E - !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E - !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E + !ALIGN 255,0 +OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E + !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E + !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E + !WORD DROP,DUP,PUSHEP,PULLEP,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E + !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E + !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E + !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E ;* ;* DIV TOS-1 BY TOS ;* -DIV JSR _DIV - LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 - BCS NEG - JMP NEXTOP +DIV JSR _DIV + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS NEG + JMP NEXTOP ;* ;* MOD TOS-1 BY TOS ;* -MOD JSR _DIV - LDA TMPL ; REMNDRL - STA ESTKL,X - LDA TMPH ; REMNDRH - STA ESTKH,X - LDA DVSIGN ; REMAINDER IS SIGN OF DIVIDEND - BMI NEG - JMP NEXTOP +MOD JSR _DIV + LDA TMPL ; REMNDRL + STA ESTKL,X + LDA TMPH ; REMNDRH + STA ESTKH,X + LDA DVSIGN ; REMAINDER IS SIGN OF DIVIDEND + BMI NEG + JMP NEXTOP ;* ;* NEGATE TOS ;* -NEG LDA #$00 - SEC - SBC ESTKL,X - STA ESTKL,X - LDA #$00 - SBC ESTKH,X - STA ESTKH,X - JMP NEXTOP +NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + JMP NEXTOP ;* ;* INTERNAL DIVIDE ALGORITHM ;* -_NEG LDA #$00 - SEC - SBC ESTKL,X - STA ESTKL,X - LDA #$00 - SBC ESTKH,X - STA ESTKH,X - RTS -_DIV STY IPY - LDY #$11 ; #BITS+1 - LDA #$00 - STA TMPL ; REMNDRL - STA TMPH ; REMNDRH - LDA ESTKH,X - AND #$80 - STA DVSIGN - BPL + - JSR _NEG - INC DVSIGN -+ LDA ESTKH+1,X - BPL + - INX - JSR _NEG - DEX - INC DVSIGN - BNE _DIV1 -+ ORA ESTKL+1,X ; DVDNDL - BEQ _DIVEX -_DIV1 ASL ESTKL+1,X ; DVDNDL - ROL ESTKH+1,X ; DVDNDH - DEY - BCC _DIV1 -_DIVLP ROL TMPL ; REMNDRL - ROL TMPH ; REMNDRH - LDA TMPL ; REMNDRL - CMP ESTKL,X ; DVSRL - LDA TMPH ; REMNDRH - SBC ESTKH,X ; DVSRH - BCC + - STA TMPH ; REMNDRH - LDA TMPL ; REMNDRL - SBC ESTKL,X ; DVSRL - STA TMPL ; REMNDRL - SEC -+ ROL ESTKL+1,X ; DVDNDL - ROL ESTKH+1,X ; DVDNDH - DEY - BNE _DIVLP -_DIVEX INX - LDY IPY - RTS +_NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +_DIV STY IPY + LDY #$11 ; #BITS+1 + LDA #$00 + STA TMPL ; REMNDRL + STA TMPH ; REMNDRH + LDA ESTKH,X + AND #$80 + STA DVSIGN + BPL + + JSR _NEG + INC DVSIGN ++ LDA ESTKH+1,X + BPL + + INX + JSR _NEG + DEX + INC DVSIGN + BNE _DIV1 ++ ORA ESTKL+1,X ; DVDNDL + BEQ _DIVEX +_DIV1 ASL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BCC _DIV1 +_DIVLP ROL TMPL ; REMNDRL + ROL TMPH ; REMNDRH + LDA TMPL ; REMNDRL + CMP ESTKL,X ; DVSRL + LDA TMPH ; REMNDRH + SBC ESTKH,X ; DVSRH + BCC + + STA TMPH ; REMNDRH + LDA TMPL ; REMNDRL + SBC ESTKL,X ; DVSRL + STA TMPL ; REMNDRL + SEC ++ ROL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BNE _DIVLP +_DIVEX INX + LDY IPY + RTS ;* ;* ADD TOS TO TOS-1 ;* -ADD LDA ESTKL,X - CLC - ADC ESTKL+1,X - STA ESTKL+1,X - LDA ESTKH,X - ADC ESTKH+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +ADD LDA ESTKL,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* SUB TOS FROM TOS-1 ;* -SUB LDA ESTKL+1,X - SEC - SBC ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - SBC ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +SUB LDA ESTKL+1,X + SEC + SBC ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + SBC ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; ;* ;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 ;* -IDXW LDA ESTKL,X - ASL - ROL ESTKH,X - CLC - ADC ESTKL+1,X - STA ESTKL+1,X - LDA ESTKH,X - ADC ESTKH+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +IDXW LDA ESTKL,X + ASL + ROL ESTKH,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* BITWISE AND TOS TO TOS-1 ;* -BAND LDA ESTKL+1,X - AND ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - AND ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +BAND LDA ESTKL+1,X + AND ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + AND ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* INCLUSIVE OR TOS TO TOS-1 ;* -IOR LDA ESTKL+1,X - ORA ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - ORA ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +IOR LDA ESTKL+1,X + ORA ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + ORA ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* EXLUSIVE OR TOS TO TOS-1 ;* -XOR LDA ESTKL+1,X - EOR ESTKL,X - STA ESTKL+1,X - LDA ESTKH+1,X - EOR ESTKH,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +XOR LDA ESTKL+1,X + EOR ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + EOR ESTKH,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 LEFT BY TOS ;* -SHL STY IPY - LDA ESTKL,X - CMP #$08 - BCC SHL1 - LDY ESTKL+1,X - STY ESTKH+1,X - LDY #$00 - STY ESTKL+1,X - SBC #$08 -SHL1 TAY - BEQ SHL3 -SHL2 ASL ESTKL+1,X - ROL ESTKH+1,X - DEY - BNE SHL2 -SHL3 LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SHL STY IPY + LDA ESTKL,X + CMP #$08 + BCC SHL1 + LDY ESTKL+1,X + STY ESTKH+1,X + LDY #$00 + STY ESTKL+1,X + SBC #$08 +SHL1 TAY + BEQ SHL3 +SHL2 ASL ESTKL+1,X + ROL ESTKH+1,X + DEY + BNE SHL2 +SHL3 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* SHIFT TOS-1 RIGHT BY TOS ;* -SHR STY IPY - LDA ESTKL,X - CMP #$08 - BCC SHR2 - LDY ESTKH+1,X - STY ESTKL+1,X - CPY #$80 - LDY #$00 - BCC SHR1 - DEY -SHR1 STY ESTKH+1,X - SEC - SBC #$08 -SHR2 TAY - BEQ SHR4 - LDA ESTKH+1,X -SHR3 CMP #$80 - ROR - ROR ESTKL+1,X - DEY - BNE SHR3 - STA ESTKH+1,X -SHR4 LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SHR STY IPY + LDA ESTKL,X + CMP #$08 + BCC SHR2 + LDY ESTKH+1,X + STY ESTKL+1,X + CPY #$80 + LDY #$00 + BCC SHR1 + DEY +SHR1 STY ESTKH+1,X + SEC + SBC #$08 +SHR2 TAY + BEQ SHR4 + LDA ESTKH+1,X +SHR3 CMP #$80 + ROR + ROR ESTKL+1,X + DEY + BNE SHR3 + STA ESTKH+1,X +SHR4 LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* LOGICAL NOT ;* -LNOT LDA ESTKL,X - ORA ESTKH,X - BEQ LNOT1 - LDA #$FF -LNOT1 EOR #$FF - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP +LNOT LDA ESTKL,X + ORA ESTKH,X + BEQ LNOT1 + LDA #$FF +LNOT1 EOR #$FF + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP ;* ;* LOGICAL AND ;* -LAND LDA ESTKL+1,X - ORA ESTKH+1,X - BEQ LAND2 - LDA ESTKL,X - ORA ESTKH,X - BEQ LAND1 - LDA #$FF -LAND1 STA ESTKL+1,X - STA ESTKH+1,X -;LAND2 INX -; JMP NEXTOP -LAND2 JMP DROP +LAND LDA ESTKL+1,X + ORA ESTKH+1,X + BEQ LAND2 + LDA ESTKL,X + ORA ESTKH,X + BEQ LAND1 + LDA #$FF +LAND1 STA ESTKL+1,X + STA ESTKH+1,X +;LAND2 INX +; JMP NEXTOP +LAND2 JMP DROP ;* ;* LOGICAL OR ;* -LOR LDA ESTKL,X - ORA ESTKH,X - ORA ESTKL+1,X - ORA ESTKH+1,X - BEQ LOR1 - LDA #$FF - STA ESTKL+1,X - STA ESTKH+1,X -;LOR1 INX -; JMP NEXTOP -LOR1 JMP DROP +LOR LDA ESTKL,X + ORA ESTKH,X + ORA ESTKL+1,X + ORA ESTKH+1,X + BEQ LOR1 + LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X +;LOR1 INX +; JMP NEXTOP +LOR1 JMP DROP ;* ;* DUPLICATE TOS ;* -DUP DEX - LDA ESTKL+1,X - STA ESTKL,X - LDA ESTKH+1,X - STA ESTKH,X - JMP NEXTOP +DUP DEX + LDA ESTKL+1,X + STA ESTKL,X + LDA ESTKH+1,X + STA ESTKH,X + JMP NEXTOP ;* -;* PUSH FROM EVAL STACK TO CALL STACK +;* PUSH EVAL STACK POINTER TO CALL STACK ;* -PUSH LDA ESTKL,X - PHA - LDA ESTKH,X - PHA -; INX -; JMP NEXTOP - JMP DROP +PUSHEP TXA + PHA + JMP NEXTOP ;* -;* PULL FROM CALL STACK TO EVAL STACK +;* PULL EVAL STACK POINTER FROM CALL STACK ;* -PULL DEX - PLA - STA ESTKH,X - PLA - STA ESTKL,X - JMP NEXTOP +PULLEP PLA + TAX + JMP NEXTOP ;* ;* CONSTANT ;* -ZERO DEX - LDA #$00 - STA ESTKL,X - STA ESTKH,X - JMP NEXTOP -CB DEX - +INC_IP - LDA (IP),Y - STA ESTKL,X - LDA #$00 - STA ESTKH,X - JMP NEXTOP +ZERO DEX + LDA #$00 + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +CB DEX + +INC_IP + LDA (IP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP ;* ;* LOAD ADDRESS & LOAD CONSTANT WORD (SAME THING, WITH OR WITHOUT FIXUP) ;* -LA = * -CW DEX - +INC_IP - LDA (IP),Y - STA ESTKL,X - +INC_IP - LDA (IP),Y - STA ESTKH,X - JMP NEXTOP +LA = * +CW DEX + +INC_IP + LDA (IP),Y + STA ESTKL,X + +INC_IP + LDA (IP),Y + STA ESTKH,X + JMP NEXTOP ;* ;* CONSTANT STRING ;* -CS DEX - +INC_IP - TYA ; NORMALIZE IP AND SAVE STRING ADDR ON ESTK - CLC - ADC IPL - STA IPL - STA ESTKL,X - LDA #$00 - TAY - ADC IPH - STA IPH - STA ESTKH,X - LDA (IP),Y - TAY - JMP NEXTOP +CS DEX + +INC_IP + TYA ; NORMALIZE IP AND SAVE STRING ADDR ON ESTK + CLC + ADC IPL + STA IPL + STA ESTKL,X + LDA #$00 + TAY + ADC IPH + STA IPH + STA ESTKH,X + LDA (IP),Y + TAY + JMP NEXTOP ;* ;* LOAD VALUE FROM ADDRESS TAG ;* -LB LDA ESTKL,X - STA TMPL - LDA ESTKH,X - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - STA ESTKL,X - STY ESTKH,X - LDY IPY - JMP NEXTOP -LW LDA ESTKL,X - STA TMPL - LDA ESTKH,X - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - STA ESTKL,X - INY - LDA (TMP),Y - STA ESTKH,X - LDY IPY - JMP NEXTOP +LB LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + STA ESTKL,X + STY ESTKH,X + LDY IPY + JMP NEXTOP +LW LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP ;* ;* LOAD ADDRESS OF LOCAL FRAME OFFSET ;* -LLA +INC_IP - LDA (IP),Y - DEX - CLC - ADC IFPL - STA ESTKL,X - LDA #$00 - ADC IFPH - STA ESTKH,X - JMP NEXTOP +LLA +INC_IP + LDA (IP),Y + DEX + CLC + ADC IFPL + STA ESTKL,X + LDA #$00 + ADC IFPH + STA ESTKH,X + JMP NEXTOP ;* ;* LOAD VALUE FROM LOCAL FRAME OFFSET ;* -LLB +INC_IP - LDA (IP),Y - STY IPY - TAY - DEX - LDA (IFP),Y - STA ESTKL,X - LDA #$00 - STA ESTKH,X - LDY IPY - JMP NEXTOP -LLW +INC_IP - LDA (IP),Y - STY IPY - TAY - DEX - LDA (IFP),Y - STA ESTKL,X - INY - LDA (IFP),Y - STA ESTKH,X - LDY IPY - JMP NEXTOP +LLB +INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + LDY IPY + JMP NEXTOP +LLW +INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + INY + LDA (IFP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP ;* ;* LOAD VALUE FROM ABSOLUTE ADDRESS ;* -LAB +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - DEX - STA ESTKL,X - STY ESTKH,X - LDY IPY - JMP NEXTOP -LAW +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA (TMP),Y - DEX - STA ESTKL,X - INY - LDA (TMP),Y - STA ESTKH,X - LDY IPY - JMP NEXTOP +LAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + STY ESTKH,X + LDY IPY + JMP NEXTOP +LAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP ;* ;* STORE VALUE TO ADDRESS ;* -SB LDA ESTKL+1,X - STA TMPL - LDA ESTKH+1,X - STA TMPH - LDA ESTKL,X - STY IPY - LDY #$00 - STA (TMP),Y - LDY IPY - INX -; INX -; JMP NEXTOP - JMP DROP -SW LDA ESTKL+1,X - STA TMPL - LDA ESTKH+1,X - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - INY - LDA ESTKH,X - STA (TMP),Y - LDY IPY - INX -; INX -; JMP NEXTOP - JMP DROP +SB LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + LDA ESTKL+1,X + STY IPY + LDY #$00 + STA (TMP),Y + LDY IPY + INX +; INX +; JMP NEXTOP + JMP DROP +SW LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL+1,X + STA (TMP),Y + INY + LDA ESTKH+1,X + STA (TMP),Y + LDY IPY + INX +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET ;* -SLB +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP -SLW +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - INY - LDA ESTKH,X - STA (IFP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SLB +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +SLW +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK ;* -DLB +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - LDY IPY - JMP NEXTOP -DLW +INC_IP - LDA (IP),Y - STY IPY - TAY - LDA ESTKL,X - STA (IFP),Y - INY - LDA ESTKH,X - STA (IFP),Y - LDY IPY - JMP NEXTOP +DLB +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY + JMP NEXTOP +DLW +INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY + JMP NEXTOP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS ;* -SAB +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - LDA ESTKL,X - STY IPY - LDY #$00 - STA (TMP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP -SAW +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - INY - LDA ESTKH,X - STA (TMP),Y - LDY IPY -; INX -; JMP NEXTOP - JMP DROP +SAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + LDA ESTKL,X + STY IPY + LDY #$00 + STA (TMP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP +SAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY +; INX +; JMP NEXTOP + JMP DROP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK ;* -DAB +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - LDY IPY - JMP NEXTOP -DAW +INC_IP - LDA (IP),Y - STA TMPL - +INC_IP - LDA (IP),Y - STA TMPH - STY IPY - LDY #$00 - LDA ESTKL,X - STA (TMP),Y - INY - LDA ESTKH,X - STA (TMP),Y - LDY IPY - JMP NEXTOP +DAB +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + LDY IPY + JMP NEXTOP +DAW +INC_IP + LDA (IP),Y + STA TMPL + +INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + JMP NEXTOP ;* ;* COMPARES ;* -ISEQ LDA ESTKL,X - CMP ESTKL+1,X - BNE ISFLS - LDA ESTKH,X - CMP ESTKH+1,X - BNE ISFLS -ISTRU LDA #$FF - STA ESTKL+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +ISEQ LDA ESTKL,X + CMP ESTKL+1,X + BNE ISFLS + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISFLS +ISTRU LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; -ISNE LDA ESTKL,X - CMP ESTKL+1,X - BNE ISTRU - LDA ESTKH,X - CMP ESTKH+1,X - BNE ISTRU -ISFLS LDA #$00 - STA ESTKL+1,X - STA ESTKH+1,X -; INX -; JMP NEXTOP - JMP DROP +ISNE LDA ESTKL,X + CMP ESTKL+1,X + BNE ISTRU + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISTRU +ISFLS LDA #$00 + STA ESTKL+1,X + STA ESTKH+1,X +; INX +; JMP NEXTOP + JMP DROP ; -ISGE LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - BVC ISGE1 - EOR #$80 -ISGE1 BPL ISTRU - BMI ISFLS +ISGE LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVC ISGE1 + EOR #$80 +ISGE1 BPL ISTRU + BMI ISFLS ; -ISGT LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - BVC ISGT1 - EOR #$80 -ISGT1 BMI ISTRU - BPL ISFLS +ISGT LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVC ISGT1 + EOR #$80 +ISGT1 BMI ISTRU + BPL ISFLS ; -ISLE LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - BVC ISLE1 - EOR #$80 -ISLE1 BPL ISTRU - BMI ISFLS +ISLE LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVC ISLE1 + EOR #$80 +ISLE1 BPL ISTRU + BMI ISFLS ; -ISLT LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - BVC ISLT1 - EOR #$80 -ISLT1 BMI ISTRU - BPL ISFLS +ISLT LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVC ISLT1 + EOR #$80 +ISLT1 BMI ISTRU + BPL ISFLS ;* ;* BRANCHES ;* -BRTRU INX - LDA ESTKH-1,X - ORA ESTKL-1,X - BNE BRNCH -NOBRNCH +INC_IP - +INC_IP - JMP NEXTOP -BRFLS INX - LDA ESTKH-1,X - ORA ESTKL-1,X - BNE NOBRNCH -BRNCH LDA IPH - STA TMPH - LDA IPL - +INC_IP - CLC - ADC (IP),Y - STA TMPL - LDA TMPH - +INC_IP - ADC (IP),Y - STA IPH - LDA TMPL - STA IPL - DEY - DEY - JMP NEXTOP -BREQ INX - LDA ESTKL-1,X - CMP ESTKL,X - BNE NOBRNCH - LDA ESTKH-1,X - CMP ESTKH,X - BEQ BRNCH - BNE NOBRNCH -BRNE INX - LDA ESTKL-1,X - CMP ESTKL,X - BNE BRNCH - LDA ESTKH-1,X - CMP ESTKH,X - BEQ NOBRNCH - BNE BRNCH -BRGT INX - LDA ESTKL-1,X - CMP ESTKL,X - LDA ESTKH-1,X - SBC ESTKH,X - BMI BRNCH - BPL NOBRNCH -BRLT INX - LDA ESTKL,X - CMP ESTKL-1,X - LDA ESTKH,X - SBC ESTKH-1,X - BMI BRNCH - BPL NOBRNCH -IBRNCH LDA IPL - CLC - ADC ESTKL,X - STA IPL - LDA IPH - ADC ESTKH,X - STA IPH -; INX -; JMP NEXTOP - JMP DROP +BRTRU INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE BRNCH +NOBRNCH +INC_IP + +INC_IP + JMP NEXTOP +BRFLS INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE NOBRNCH +BRNCH LDA IPH + STA TMPH + LDA IPL + +INC_IP + CLC + ADC (IP),Y + STA TMPL + LDA TMPH + +INC_IP + ADC (IP),Y + STA IPH + LDA TMPL + STA IPL + DEY + DEY + JMP NEXTOP +BREQ INX + LDA ESTKL-1,X + CMP ESTKL,X + BNE NOBRNCH + LDA ESTKH-1,X + CMP ESTKH,X + BEQ BRNCH + BNE NOBRNCH +BRNE INX + LDA ESTKL-1,X + CMP ESTKL,X + BNE BRNCH + LDA ESTKH-1,X + CMP ESTKH,X + BEQ NOBRNCH + BNE BRNCH +BRGT INX + LDA ESTKL-1,X + CMP ESTKL,X + LDA ESTKH-1,X + SBC ESTKH,X + BMI BRNCH + BPL NOBRNCH +BRLT INX + LDA ESTKL,X + CMP ESTKL-1,X + LDA ESTKH,X + SBC ESTKH-1,X + BMI BRNCH + BPL NOBRNCH +IBRNCH LDA IPL + CLC + ADC ESTKL,X + STA IPL + LDA IPH + ADC ESTKH,X + STA IPH +; INX +; JMP NEXTOP + JMP DROP ;* ;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) ;* -CALL +INC_IP - LDA (IP),Y - STA CALLADR+1 - +INC_IP - LDA (IP),Y - STA CALLADR+2 - LDA IPH - PHA - LDA IPL - PHA - TYA - PHA -CALLADR JSR $FFFF - PLA - TAY - PLA - STA IPL - PLA - STA IPH - JMP NEXTOP +CALL +INC_IP + LDA (IP),Y + STA CALLADR+1 + +INC_IP + LDA (IP),Y + STA CALLADR+2 + LDA IPH + PHA + LDA IPL + PHA + TYA + PHA +CALLADR JSR $FFFF + PLA + TAY + PLA + STA IPL + PLA + STA IPH + JMP NEXTOP ;* ;* INDIRECT CALL TO ADDRESS (NATIVE CODE) ;* -ICAL LDA ESTKL,X - STA ICALADR+1 - LDA ESTKH,X - STA ICALADR+2 - INX - LDA IPH - PHA - LDA IPL - PHA - TYA - PHA -ICALADR JSR $FFFF - PLA - TAY - PLA - STA IPL - PLA - STA IPH - JMP NEXTOP +ICAL LDA ESTKL,X + STA ICALADR+1 + LDA ESTKH,X + STA ICALADR+2 + INX + LDA IPH + PHA + LDA IPL + PHA + TYA + PHA +ICALADR JSR $FFFF + PLA + TAY + PLA + STA IPL + PLA + STA IPH + JMP NEXTOP ;* ;* ENTER FUNCTION WITH FRAME SIZE AND PARAM COUNT ;* -ENTER INY - LDA (IP),Y - PHA ; SAVE ON STACK FOR LEAVE - EOR #$FF - SEC - ADC IFPL - STA IFPL - BCS + - DEC IFPH -+ INY - LDA (IP),Y - ASL - TAY - BEQ + -- LDA ESTKH,X - DEY - STA (IFP),Y - LDA ESTKL,X - INX - DEY - STA (IFP),Y - BNE - -+ LDY #$02 - JMP NEXTOP +ENTER INY + LDA (IP),Y + PHA ; SAVE ON STACK FOR LEAVE + EOR #$FF + SEC + ADC IFPL + STA IFPL + BCS + + DEC IFPH ++ INY + LDA (IP),Y + ASL + TAY + BEQ + +- LDA ESTKH,X + DEY + STA (IFP),Y + LDA ESTKL,X + INX + DEY + STA (IFP),Y + BNE - ++ LDY #$02 + JMP NEXTOP ;* ;* LEAVE FUNCTION ;* -LEAVE PLA - CLC - ADC IFPL - STA IFPL - BCS LIFPH - RTS -LIFPH INC IFPH -RET RTS -A1CMD !SOURCE "vmsrc/a1cmd.a" -SEGEND = * -VMINIT LDY #$10 ; INSTALL PAGE 0 FETCHOP ROUTINE -- LDA PAGE0-1,Y - STA DROP-1,Y - DEY - BNE - - STY IFPL ; INIT FRAME POINTER - LDA #$80 - STA IFPH - LDA #SEGEND - STA SRCH - LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX - JMP A1CMD -PAGE0 = * - !PSEUDOPC $00EF { +LEAVE PLA + CLC + ADC IFPL + STA IFPL + BCS LIFPH + RTS +LIFPH INC IFPH +RET RTS +A1CMD !SOURCE "vmsrc/a1cmd.a" +SEGEND = * +VMINIT LDY #$10 ; INSTALL PAGE 0 FETCHOP ROUTINE +- LDA PAGE0-1,Y + STA DROP-1,Y + DEY + BNE - + STY IFPL ; INIT FRAME POINTER + LDA #$80 + STA IFPH + LDA #SEGEND + STA SRCH + LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX + JMP A1CMD +PAGE0 = * + !PSEUDOPC $00EF { ;* ;* INTERP BYTECODE INNER LOOP ;* - INX ; DROP - INY ; NEXTOP - BEQ NEXTOPH - LDA $FFFF,Y ; FETCHOP @ $F3, IP MAPS OVER $FFFF @ $F4 - STA OPIDX - JMP (OPTBL) -NEXTOPH INC IPH - BNE FETCHOP + INX ; DROP + INY ; NEXTOP + BEQ NEXTOPH + LDA $FFFF,Y ; FETCHOP @ $F3, IP MAPS OVER $FFFF @ $F4 + STA OPIDX + JMP (OPTBL) +NEXTOPH INC IPH + BNE FETCHOP } diff --git a/src/vmsrc/plvm02.s b/src/vmsrc/plvm02.s old mode 100644 new mode 100755 index d1b3243..7aeb36a --- a/src/vmsrc/plvm02.s +++ b/src/vmsrc/plvm02.s @@ -1,64 +1,64 @@ ;********************************************************** ;* -;* APPLE ][ 64K/128K PLASMA INTERPETER +;* APPLE ][ 64K/128K PLASMA INTERPRETER ;* -;* SYSTEM ROUTINES AND LOCATIONS +;* SYSTEM ROUTINES AND LOCATIONS ;* ;********************************************************** ;* ;* MONITOR SPECIAL LOCATIONS ;* -CSWL = $36 -CSWH = $37 -PROMPT = $33 +CSWL = $36 +CSWH = $37 +PROMPT = $33 ;* ;* PRODOS ;* -PRODOS = $BF00 -DEVCNT = $BF31 ; GLOBAL PAGE DEVICE COUNT -DEVLST = $BF32 ; GLOBAL PAGE DEVICE LIST -MACHID = $BF98 ; GLOBAL PAGE MACHINE ID BYTE -RAMSLOT = $BF26 ; SLOT 3, DRIVE 2 IS /RAM'S DRIVER VECTOR -NODEV = $BF10 +PRODOS = $BF00 +DEVCNT = $BF31 ; GLOBAL PAGE DEVICE COUNT +DEVLST = $BF32 ; GLOBAL PAGE DEVICE LIST +MACHID = $BF98 ; GLOBAL PAGE MACHINE ID BYTE +RAMSLOT = $BF26 ; SLOT 3, DRIVE 2 IS /RAM'S DRIVER VECTOR +NODEV = $BF10 ;* ;* HARDWARE ADDRESSES ;* -KEYBD = $C000 -CLRKBD = $C010 -SPKR = $C030 -LCRDEN = $C080 -LCWTEN = $C081 -ROMEN = $C082 -LCRWEN = $C083 -LCBNK2 = $00 -LCBNK1 = $08 -ALTZPOFF= $C008 -ALTZPON = $C009 -ALTRDOFF= $C002 -ALTRDON = $C003 -ALTWROFF= $C004 -ALTWRON = $C005 - !SOURCE "vmsrc/plvmzp.inc" -STRBUF = $0280 -INTERP = $03D0 +KEYBD = $C000 +CLRKBD = $C010 +SPKR = $C030 +LCRDEN = $C080 +LCWTEN = $C081 +ROMEN = $C082 +LCRWEN = $C083 +LCBNK2 = $00 +LCBNK1 = $08 +ALTZPOFF= $C008 +ALTZPON = $C009 +ALTRDOFF= $C002 +ALTRDON = $C003 +ALTWROFF= $C004 +ALTWRON = $C005 + !SOURCE "vmsrc/plvmzp.inc" +STRBUF = $0280 +INTERP = $03D0 ;* ;* INTERPRETER INSTRUCTION POINTER INCREMENT MACRO ;* !MACRO INC_IP { INY - BNE * + 4 - INC IPH + BNE * + 4 + INC IPH } ;****************************** ;* * ;* INTERPRETER INITIALIZATION * ;* * ;****************************** -* = $2000 - LDX #$FE +* = $2000 + LDX #$FE TXS - LDX #$00 - STX $01FF + LDX #$00 + STX $01FF ;* ;* DISCONNECT /RAM ;* @@ -73,25 +73,25 @@ INTERP = $03D0 LDA RAMSLOT+1 CMP NODEV+1 BEQ RAMDONE -RAMCONT LDY DEVCNT -RAMLOOP LDA DEVLST,Y +RAMCONT LDY DEVCNT +RAMLOOP LDA DEVLST,Y AND #$F3 CMP #$B3 BEQ GETLOOP DEY BPL RAMLOOP BMI RAMDONE -GETLOOP LDA DEVLST+1,Y +GETLOOP LDA DEVLST+1,Y STA DEVLST,Y BEQ RAMEXIT INY BNE GETLOOP -RAMEXIT LDA NODEV +RAMEXIT LDA NODEV STA RAMSLOT LDA NODEV+1 STA RAMSLOT+1 DEC DEVCNT -RAMDONE CLI +RAMDONE CLI ;* ;* MOVE VM INTO LANGUAGE CARD ;* @@ -105,7 +105,7 @@ RAMDONE CLI STY DSTL LDA #$D0 STA DSTH -- LDA (SRC),Y ; COPY VM+CMD INTO LANGUAGE CARD +- LDA (SRC),Y ; COPY VM+CMD INTO LANGUAGE CARD STA (DST),Y INY BNE - @@ -117,7 +117,7 @@ RAMDONE CLI ;* ;* MOVE FIRST PAGE OF 'BYE' INTO PLACE ;* - STY SRCL + STY SRCL LDA #$D1 STA SRCH - LDA (SRC),Y @@ -127,7 +127,7 @@ RAMDONE CLI ;* ;* SAVE DEFAULT COMMAND INTERPRETER PATH IN LC ;* - JSR PRODOS ; GET PREFIX + JSR PRODOS ; GET PREFIX !BYTE $C7 !WORD GETPFXPARMS LDY STRBUF ; APPEND "CMD" @@ -146,13 +146,13 @@ RAMDONE CLI INY STA STRBUF,Y STY STRBUF - BIT LCRWEN+LCBNK2 ; COPY TO LC FOR BYE + BIT LCRWEN+LCBNK2 ; COPY TO LC FOR BYE BIT LCRWEN+LCBNK2 - LDA STRBUF,Y STA LCDEFCMD,Y DEY BPL - - JMP CMDENTRY + JMP CMDENTRY GETPFXPARMS !BYTE 1 !WORD STRBUF ; PATH STRING GOES HERE ;************************************************ @@ -160,7 +160,7 @@ GETPFXPARMS !BYTE 1 ;* LANGUAGE CARD RESIDENT PLASMA VM STARTS HERE * ;* * ;************************************************ -VMCORE = * +VMCORE = * !PSEUDOPC $D000 { ;**************** ;* * @@ -168,12 +168,12 @@ VMCORE = * ;* * ;**************** !ALIGN 255,0 -OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E +OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E - !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + !WORD DROP,DUP,PUSHEP,PULLEP,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E - !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E + !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E ;* @@ -182,10 +182,10 @@ OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E DINTRP PLA CLC ADC #$01 - STA IPL - PLA + STA IPL + PLA ADC #$00 - STA IPH + STA IPH LDA IFPH PHA ; SAVE ON STACK FOR LEAVE/RET LDA IFPL @@ -199,16 +199,16 @@ DINTRP PLA STA OPPAGE JMP FETCHOP IINTRP PLA - STA TMPL - PLA - STA TMPH + STA TMPL + PLA + STA TMPH LDY #$02 - LDA (TMP),Y - STA IPH + LDA (TMP),Y + STA IPH DEY - LDA (TMP),Y + LDA (TMP),Y STA IPL - DEY + DEY LDA IFPH PHA ; SAVE ON STACK FOR LEAVE/RET LDA IFPL @@ -219,18 +219,18 @@ IINTRP PLA STA IFPH LDA #>OPTBL STA OPPAGE - JMP FETCHOP -IINTRPX PLA - STA TMPL - PLA - STA TMPH + JMP FETCHOP +IINTRPX PLA + STA TMPL + PLA + STA TMPH LDY #$02 - LDA (TMP),Y - STA IPH + LDA (TMP),Y + STA IPH DEY - LDA (TMP),Y + LDA (TMP),Y STA IPL - DEY + DEY LDA IFPH PHA ; SAVE ON STACK FOR LEAVE/RET LDA IFPL @@ -277,7 +277,7 @@ CMDENTRY = * ; INSTALL PAGE 0 FETCHOP ROUTINE ; LDY #$0F -- LDA PAGE0,Y +- LDA PAGE0,Y STA DROP,Y DEY BPL - @@ -285,35 +285,35 @@ CMDENTRY = * ; INSTALL PAGE 3 VECTORS ; LDY #$12 -- LDA PAGE3,Y +- LDA PAGE3,Y STA INTERP,Y DEY BPL - ; ; READ CMD INTO MEMORY ; - JSR PRODOS ; CLOSE EVERYTHING + JSR PRODOS ; CLOSE EVERYTHING !BYTE $CC !WORD CLOSEPARMS - BNE FAIL - JSR PRODOS ; OPEN CMD + BNE FAIL + JSR PRODOS ; OPEN CMD !BYTE $C8 !WORD OPENPARMS BNE FAIL - LDA REFNUM - STA READPARMS+1 - JSR PRODOS + LDA REFNUM + STA READPARMS+1 + JSR PRODOS !BYTE $CA !WORD READPARMS - BNE FAIL - JSR PRODOS + BNE FAIL + JSR PRODOS !BYTE $CC !WORD CLOSEPARMS - BNE FAIL + BNE FAIL ; ; INIT VM ENVIRONMENT STACK POINTERS ; -; LDA #$00 ; INIT FRAME POINTER +; LDA #$00 ; INIT FRAME POINTER STA PPL STA IFPL LDA #$BF @@ -321,8 +321,8 @@ CMDENTRY = * STA IFPH LDX #$FE ; INIT STACK POINTER (YES, $FE. SEE GETS) TXS - LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX - JMP $2000 ; JUMP TO LOADED SYSTEM COMMAND + LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX + JMP $2000 ; JUMP TO LOADED SYSTEM COMMAND ; ; PRINT FAIL MESSAGE, WAIT FOR KEYPRESS, AND REBOOT ; @@ -335,33 +335,33 @@ FAIL INC $3F4 ; INVALIDATE POWER-UP BYTE BPL - JSR $FD0C ; WAIT FOR KEYPRESS JMP ($FFFC) ; RESET -OPENPARMS !BYTE 3 +OPENPARMS !BYTE 3 !WORD STRBUF !WORD $0800 REFNUM !BYTE 0 -READPARMS !BYTE 4 +READPARMS !BYTE 4 !BYTE 0 !WORD $2000 !WORD $9F00 !WORD 0 CLOSEPARMS !BYTE 1 !BYTE 0 -DISABLE80 !BYTE 21, 13, '1', 26, 13 +DISABLE80 !BYTE 21, 13, '1', 26, 13 FAILMSG !TEXT "...TESER OT YEK YNA .DMC GNISSIM" -PAGE0 = * +PAGE0 = * ;****************************** ;* * ;* INTERP BYTECODE INNER LOOP * ;* * ;****************************** - !PSEUDOPC $00EF { + !PSEUDOPC $00EF { INX ; DROP @ $EF - INY ; NEXTOP @ $F0 + INY ; NEXTOP @ $F0 BEQ NEXTOPH LDA $FFFF,Y ; FETCHOP @ $F3, IP MAPS OVER $FFFF @ $F4 STA OPIDX JMP (OPTBL) ; OPIDX AND OPPAGE MAP OVER OPTBL -NEXTOPH INC IPH +NEXTOPH INC IPH BNE FETCHOP } PAGE3 = * @@ -386,10 +386,10 @@ LCDEFCMD = *-28 ; DEFCMD IN LC MEMORY ;* * ;***************** !ALIGN 255,0 -OPXTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E - !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E +OPXTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E + !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CSX ; 20 22 24 26 28 2A 2C 2E - !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + !WORD DROP,DUP,PUSHEP,PULLEP,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E !WORD BRNCH,IBRNCH,CALLX,ICALX,ENTER,LEAVEX,RETX,NEXTOP; 50 52 54 56 58 5A 5C 5E !WORD LBX,LWX,LLBX,LLWX,LABX,LAWX,DLB,DLW ; 60 62 64 66 68 6A 6C 6E @@ -397,7 +397,7 @@ OPXTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E ;* ;* ADD TOS TO TOS-1 ;* -ADD LDA ESTKL,X +ADD LDA ESTKL,X CLC ADC ESTKL+1,X STA ESTKL+1,X @@ -410,7 +410,7 @@ ADD LDA ESTKL,X ;* ;* SUB TOS FROM TOS-1 ;* -SUB LDA ESTKL+1,X +SUB LDA ESTKL+1,X SEC SBC ESTKL,X STA ESTKL+1,X @@ -423,7 +423,7 @@ SUB LDA ESTKL+1,X ;* ;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 ;* -IDXW LDA ESTKL,X +IDXW LDA ESTKL,X ASL ROL ESTKH,X CLC @@ -447,18 +447,18 @@ MUL STY IPY EOR #$FF STA TMPH LDA #$00 - STA ESTKL+1,X ; PRODL -; STA ESTKH+1,X ; PRODH -MULLP LSR TMPH ; MULTPLRH + STA ESTKL+1,X ; PRODL +; STA ESTKH+1,X ; PRODH +MULLP LSR TMPH ; MULTPLRH ROR TMPL ; MULTPLRL BCS + - STA ESTKH+1,X ; PRODH + STA ESTKH+1,X ; PRODH LDA ESTKL,X ; MULTPLNDL - ADC ESTKL+1,X ; PRODL + ADC ESTKL+1,X ; PRODL STA ESTKL+1,X - LDA ESTKH,X ; MULTPLNDH - ADC ESTKH+1,X ; PRODH -+ ASL ESTKL,X ; MULTPLNDL + LDA ESTKH,X ; MULTPLNDH + ADC ESTKH+1,X ; PRODH ++ ASL ESTKL,X ; MULTPLNDL ROL ESTKH,X ; MULTPLNDH DEY BNE MULLP @@ -470,7 +470,7 @@ MULLP LSR TMPH ; MULTPLRH ;* ;* INTERNAL DIVIDE ALGORITHM ;* -_NEG LDA #$00 +_NEG LDA #$00 SEC SBC ESTKL,X STA ESTKL,X @@ -479,7 +479,7 @@ _NEG LDA #$00 STA ESTKH,X RTS _DIV STY IPY - LDY #$11 ; #BITS+1 + LDY #$11 ; #BITS+1 LDA #$00 STA TMPL ; REMNDRL STA TMPH ; REMNDRH @@ -489,29 +489,29 @@ _DIV STY IPY BPL + JSR _NEG INC DVSIGN -+ LDA ESTKH+1,X ++ LDA ESTKH+1,X BPL + INX JSR _NEG DEX INC DVSIGN BNE _DIV1 -+ ORA ESTKL+1,X ; DVDNDL ++ ORA ESTKL+1,X ; DVDNDL BEQ _DIVEX -_DIV1 ASL ESTKL+1,X ; DVDNDL +_DIV1 ASL ESTKL+1,X ; DVDNDL ROL ESTKH+1,X ; DVDNDH DEY BCC _DIV1 -_DIVLP ROL TMPL ; REMNDRL +_DIVLP ROL TMPL ; REMNDRL ROL TMPH ; REMNDRH LDA TMPL ; REMNDRL - CMP ESTKL,X ; DVSRL + CMP ESTKL,X ; DVSRL LDA TMPH ; REMNDRH - SBC ESTKH,X ; DVSRH + SBC ESTKH,X ; DVSRH BCC + STA TMPH ; REMNDRH LDA TMPL ; REMNDRL - SBC ESTKL,X ; DVSRL + SBC ESTKL,X ; DVSRL STA TMPL ; REMNDRL SEC + ROL ESTKL+1,X ; DVDNDL @@ -524,7 +524,7 @@ _DIVEX INX ;* ;* NEGATE TOS ;* -NEG LDA #$00 +NEG LDA #$00 SEC SBC ESTKL,X STA ESTKL,X @@ -535,7 +535,7 @@ NEG LDA #$00 ;* ;* DIV TOS-1 BY TOS ;* -DIV JSR _DIV +DIV JSR _DIV LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 BCS NEG JMP NEXTOP @@ -553,22 +553,22 @@ MOD JSR _DIV ;* ;* INCREMENT TOS ;* -INCR INC ESTKL,X +INCR INC ESTKL,X BNE INCR1 INC ESTKH,X -INCR1 JMP NEXTOP +INCR1 JMP NEXTOP ;* ;* DECREMENT TOS ;* -DECR LDA ESTKL,X +DECR LDA ESTKL,X BNE DECR1 DEC ESTKH,X -DECR1 DEC ESTKL,X +DECR1 DEC ESTKL,X JMP NEXTOP ;* ;* BITWISE COMPLIMENT TOS ;* -COMP LDA #$FF +COMP LDA #$FF EOR ESTKL,X STA ESTKL,X LDA #$FF @@ -578,11 +578,11 @@ COMP LDA #$FF ;* ;* BITWISE AND TOS TO TOS-1 ;* -BAND LDA ESTKL+1,X +BAND LDA ESTKL+1,X AND ESTKL,X STA ESTKL+1,X LDA ESTKH+1,X - AND ESTKH,X + AND ESTKH,X STA ESTKH+1,X ; INX ; JMP NEXTOP @@ -590,7 +590,7 @@ BAND LDA ESTKL+1,X ;* ;* INCLUSIVE OR TOS TO TOS-1 ;* -IOR LDA ESTKL+1,X +IOR LDA ESTKL+1,X ORA ESTKL,X STA ESTKL+1,X LDA ESTKH+1,X @@ -602,7 +602,7 @@ IOR LDA ESTKL+1,X ;* ;* EXLUSIVE OR TOS TO TOS-1 ;* -XOR LDA ESTKL+1,X +XOR LDA ESTKL+1,X EOR ESTKL,X STA ESTKL+1,X LDA ESTKH+1,X @@ -623,13 +623,13 @@ SHL STY IPY LDY #$00 STY ESTKL+1,X SBC #$08 -SHL1 TAY +SHL1 TAY BEQ SHL3 -SHL2 ASL ESTKL+1,X +SHL2 ASL ESTKL+1,X ROL ESTKH+1,X DEY BNE SHL2 -SHL3 LDY IPY +SHL3 LDY IPY ; INX ; JMP NEXTOP JMP DROP @@ -646,19 +646,19 @@ SHR STY IPY LDY #$00 BCC SHR1 DEY -SHR1 STY ESTKH+1,X +SHR1 STY ESTKH+1,X SEC SBC #$08 -SHR2 TAY +SHR2 TAY BEQ SHR4 LDA ESTKH+1,X -SHR3 CMP #$80 +SHR3 CMP #$80 ROR ROR ESTKL+1,X DEY BNE SHR3 STA ESTKH+1,X -SHR4 LDY IPY +SHR4 LDY IPY ; INX ; JMP NEXTOP JMP DROP @@ -676,14 +676,14 @@ LNOT1 EOR #$FF ;* ;* LOGICAL AND ;* -LAND LDA ESTKL+1,X +LAND LDA ESTKL+1,X ORA ESTKH+1,X BEQ LAND2 LDA ESTKL,X ORA ESTKH,X BEQ LAND1 LDA #$FF -LAND1 STA ESTKL+1,X +LAND1 STA ESTKL+1,X STA ESTKH+1,X ;LAND2 INX ; JMP NEXTOP @@ -691,13 +691,13 @@ LAND2 JMP DROP ;* ;* LOGICAL OR ;* -LOR LDA ESTKL,X +LOR LDA ESTKL,X ORA ESTKH,X ORA ESTKL+1,X ORA ESTKH+1,X BEQ LOR1 LDA #$FF - STA ESTKL+1,X + STA ESTKL+1,X STA ESTKH+1,X ;LOR1 INX ; JMP NEXTOP @@ -705,40 +705,33 @@ LOR1 JMP DROP ;* ;* DUPLICATE TOS ;* -DUP DEX +DUP DEX LDA ESTKL+1,X STA ESTKL,X LDA ESTKH+1,X STA ESTKH,X JMP NEXTOP ;* -;* PUSH FROM EVAL STACK TO CALL STACK +;* PUSH EVAL STACK POINTER TO CALL STACK ;* -PUSH LDA ESTKL,X +PUSHEP TXA PHA - LDA ESTKH,X - PHA -; INX -; JMP NEXTOP - JMP DROP + JMP NEXTOP ;* -;* PULL FROM CALL STACK TO EVAL STACK +;* PULL EVAL STACK POINTER FROM CALL STACK ;* -PULL DEX - PLA - STA ESTKH,X - PLA - STA ESTKL,X +PULLEP PLA + TAX JMP NEXTOP ;* ;* CONSTANT ;* -ZERO DEX +ZERO DEX LDA #$00 STA ESTKL,X STA ESTKH,X JMP NEXTOP -CB DEX +CB DEX +INC_IP LDA (IP),Y STA ESTKL,X @@ -751,10 +744,10 @@ CB DEX LA = * CW DEX +INC_IP - LDA (IP),Y + LDA (IP),Y STA ESTKL,X +INC_IP - LDA (IP),Y + LDA (IP),Y STA ESTKH,X JMP NEXTOP ;* @@ -776,21 +769,21 @@ CS DEX TAY JMP NEXTOP ; -CSX DEX +CSX DEX +INC_IP TYA ; NORMALIZE IP CLC - ADC IPL + ADC IPL STA IPL - LDA #$00 + LDA #$00 TAY - ADC IPH - STA IPH - LDA PPL ; SCAN POOL FOR STRING ALREADY THERE - STA TMPL + ADC IPH + STA IPH + LDA PPL ; SCAN POOL FOR STRING ALREADY THERE + STA TMPL LDA PPH STA TMPH -_CMPPSX ;LDA TMPH ; CHECK FOR END OF POOL +_CMPPSX ;LDA TMPH ; CHECK FOR END OF POOL CMP IFPH BCC _CMPSX ; CHECK FOR MATCHING STRING BNE _CPYSX ; BEYOND END OF POOL, COPY STRING OVER @@ -803,8 +796,8 @@ _CMPSX STA ALTRDOFF CMP (IP),Y ; COMPARE STRING LENGTHS BNE _CNXTSX1 TAY -_CMPCSX STA ALTRDOFF - LDA (TMP),Y ; COMPARE STRING CHARS FROM END +_CMPCSX STA ALTRDOFF + LDA (TMP),Y ; COMPARE STRING CHARS FROM END STA ALTRDON CMP (IP),Y BNE _CNXTSX @@ -815,7 +808,7 @@ _CMPCSX STA ALTRDOFF LDA TMPH STA ESTKH,X BNE _CEXSX -_CNXTSX LDY #$00 +_CNXTSX LDY #$00 STA ALTRDOFF LDA (TMP),Y STA ALTRDON @@ -837,7 +830,7 @@ _CPYSX LDA (IP),Y ; COPY STRING FROM AUX TO MAIN MEM POOL ADC PPH STA PPH STA ESTKH,X ; COPY STRING FROM AUX MEM BYTECODE TO MAIN MEM POOL -_CPYSX1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE +_CPYSX1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE STA (PP),Y ; ALTWR IS OFF, NO NEED TO CHANGE IT HERE DEY CPY #$FF @@ -849,7 +842,7 @@ _CEXSX LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING ;* ;* LOAD VALUE FROM ADDRESS TAG ;* -LB LDA ESTKL,X +LB LDA ESTKL,X STA TMPL LDA ESTKH,X STA TMPH @@ -859,12 +852,12 @@ LB LDA ESTKL,X STA ESTKL,X STY ESTKH,X LDY IPY - JMP NEXTOP -LW LDA ESTKL,X + JMP NEXTOP +LW LDA ESTKL,X STA TMPL LDA ESTKH,X STA TMPH - STY IPY + STY IPY LDY #$00 LDA (TMP),Y STA ESTKL,X @@ -891,9 +884,9 @@ LWX LDA ESTKL,X STA TMPL LDA ESTKH,X STA TMPH - STY IPY + STY IPY STA ALTRDOFF - LDY #$00 + LDY #$00 LDA (TMP),Y STA ESTKL,X INY @@ -905,8 +898,8 @@ LWX LDA ESTKL,X ;* ;* LOAD ADDRESS OF LOCAL FRAME OFFSET ;* -LLA +INC_IP - LDA (IP),Y +LLA +INC_IP + LDA (IP),Y DEX CLC ADC IFPL @@ -918,8 +911,8 @@ LLA +INC_IP ;* ;* LOAD VALUE FROM LOCAL FRAME OFFSET ;* -LLB +INC_IP - LDA (IP),Y +LLB +INC_IP + LDA (IP),Y STY IPY TAY DEX @@ -929,8 +922,8 @@ LLB +INC_IP STA ESTKH,X LDY IPY JMP NEXTOP -LLW +INC_IP - LDA (IP),Y +LLW +INC_IP + LDA (IP),Y STY IPY TAY DEX @@ -943,7 +936,7 @@ LLW +INC_IP JMP NEXTOP ; LLBX +INC_IP - LDA (IP),Y + LDA (IP),Y STY IPY TAY DEX @@ -956,7 +949,7 @@ LLBX +INC_IP LDY IPY JMP NEXTOP LLWX +INC_IP - LDA (IP),Y + LDA (IP),Y STY IPY TAY DEX @@ -972,7 +965,7 @@ LLWX +INC_IP ;* ;* LOAD VALUE FROM ABSOLUTE ADDRESS ;* -LAB +INC_IP +LAB +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -986,7 +979,7 @@ LAB +INC_IP STY ESTKH,X LDY IPY JMP NEXTOP -LAW +INC_IP +LAW +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1003,7 +996,7 @@ LAW +INC_IP LDY IPY JMP NEXTOP ; -LABX +INC_IP +LABX +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1019,7 +1012,7 @@ LABX +INC_IP STA ALTRDON LDY IPY JMP NEXTOP -LAWX +INC_IP +LAWX +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1040,11 +1033,11 @@ LAWX +INC_IP ;* ;* STORE VALUE TO ADDRESS ;* -SB LDA ESTKL+1,X +SB LDA ESTKL,X STA TMPL - LDA ESTKH+1,X + LDA ESTKH,X STA TMPH - LDA ESTKL,X + LDA ESTKL+1,X STY IPY LDY #$00 STA (TMP),Y @@ -1053,16 +1046,16 @@ SB LDA ESTKL+1,X ; INX ; JMP NEXTOP JMP DROP -SW LDA ESTKL+1,X +SW LDA ESTKL,X STA TMPL - LDA ESTKH+1,X + LDA ESTKH,X STA TMPH STY IPY LDY #$00 - LDA ESTKL,X + LDA ESTKL+1,X STA (TMP),Y INY - LDA ESTKH,X + LDA ESTKH+1,X STA (TMP),Y LDY IPY INX @@ -1072,8 +1065,8 @@ SW LDA ESTKL+1,X ;* ;* STORE VALUE TO LOCAL FRAME OFFSET ;* -SLB +INC_IP - LDA (IP),Y +SLB +INC_IP + LDA (IP),Y STY IPY TAY LDA ESTKL,X @@ -1082,8 +1075,8 @@ SLB +INC_IP ; INX ; JMP NEXTOP JMP DROP -SLW +INC_IP - LDA (IP),Y +SLW +INC_IP + LDA (IP),Y STY IPY TAY LDA ESTKL,X @@ -1092,13 +1085,13 @@ SLW +INC_IP LDA ESTKH,X STA (IFP),Y LDY IPY -; INX +; INX ; JMP NEXTOP JMP DROP ;* ;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK ;* -DLB +INC_IP +DLB +INC_IP LDA (IP),Y STY IPY TAY @@ -1106,7 +1099,7 @@ DLB +INC_IP STA (IFP),Y LDY IPY JMP NEXTOP -DLW +INC_IP +DLW +INC_IP LDA (IP),Y STY IPY TAY @@ -1120,7 +1113,7 @@ DLW +INC_IP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS ;* -SAB +INC_IP +SAB +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1134,7 +1127,7 @@ SAB +INC_IP ; INX ; JMP NEXTOP JMP DROP -SAW +INC_IP +SAW +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1154,7 +1147,7 @@ SAW +INC_IP ;* ;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK ;* -DAB +INC_IP +DAB +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1166,7 +1159,7 @@ DAB +INC_IP STA (TMP),Y LDY IPY JMP NEXTOP -DAW +INC_IP +DAW +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1203,7 +1196,7 @@ ISNE LDA ESTKL,X LDA ESTKH,X CMP ESTKH+1,X BNE ISTRU -ISFLS LDA #$00 +ISFLS LDA #$00 STA ESTKL+1,X STA ESTKH+1,X ; INX @@ -1216,7 +1209,7 @@ ISGE LDA ESTKL+1,X SBC ESTKH,X BVC ISGE1 EOR #$80 -ISGE1 BPL ISTRU +ISGE1 BPL ISTRU BMI ISFLS ; ISGT LDA ESTKL,X @@ -1225,7 +1218,7 @@ ISGT LDA ESTKL,X SBC ESTKH+1,X BVC ISGT1 EOR #$80 -ISGT1 BMI ISTRU +ISGT1 BMI ISTRU BPL ISFLS ; ISLE LDA ESTKL,X @@ -1234,7 +1227,7 @@ ISLE LDA ESTKL,X SBC ESTKH+1,X BVC ISLE1 EOR #$80 -ISLE1 BPL ISTRU +ISLE1 BPL ISTRU BMI ISFLS ; ISLT LDA ESTKL+1,X @@ -1243,19 +1236,19 @@ ISLT LDA ESTKL+1,X SBC ESTKH,X BVC ISLT1 EOR #$80 -ISLT1 BMI ISTRU +ISLT1 BMI ISTRU BPL ISFLS ;* ;* BRANCHES ;* -BRTRU INX +BRTRU INX LDA ESTKH-1,X ORA ESTKL-1,X BNE BRNCH -NOBRNCH +INC_IP +NOBRNCH +INC_IP +INC_IP JMP NEXTOP -BRFLS INX +BRFLS INX LDA ESTKH-1,X ORA ESTKL-1,X BNE NOBRNCH @@ -1275,7 +1268,7 @@ BRNCH LDA IPH DEY DEY JMP NEXTOP -BREQ INX +BREQ INX LDA ESTKL-1,X CMP ESTKL,X BNE NOBRNCH @@ -1283,7 +1276,7 @@ BREQ INX CMP ESTKH,X BEQ BRNCH BNE NOBRNCH -BRNE INX +BRNE INX LDA ESTKL-1,X CMP ESTKL,X BNE BRNCH @@ -1291,14 +1284,14 @@ BRNE INX CMP ESTKH,X BEQ NOBRNCH BNE BRNCH -BRGT INX +BRGT INX LDA ESTKL-1,X CMP ESTKL,X LDA ESTKH-1,X SBC ESTKH,X BMI BRNCH BPL NOBRNCH -BRLT INX +BRLT INX LDA ESTKL,X CMP ESTKL-1,X LDA ESTKH,X @@ -1318,7 +1311,7 @@ IBRNCH LDA IPL ;* ;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) ;* -CALL +INC_IP +CALL +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1341,7 +1334,7 @@ CALL +INC_IP STA OPPAGE JMP NEXTOP ; -CALLX +INC_IP +CALLX +INC_IP LDA (IP),Y STA TMPL +INC_IP @@ -1355,7 +1348,7 @@ CALLX +INC_IP PHA STA ALTRDOFF CLI - JSR JMPTMP + JSR JMPTMP SEI STA ALTRDON PLA @@ -1370,7 +1363,7 @@ CALLX +INC_IP ;* ;* INDIRECT CALL TO ADDRESS (NATIVE CODE) ;* -ICAL LDA ESTKL,X +ICAL LDA ESTKL,X STA TMPL LDA ESTKH,X STA TMPH @@ -1392,7 +1385,7 @@ ICAL LDA ESTKL,X STA OPPAGE JMP NEXTOP ; -ICALX LDA ESTKL,X +ICALX LDA ESTKL,X STA TMPL LDA ESTKH,X STA TMPH @@ -1424,7 +1417,7 @@ JMPTMP JMP (TMP) ;* ;* ENTER FUNCTION WITH FRAME SIZE AND PARAM COUNT ;* -ENTER INY +ENTER INY LDA (IP),Y PHA ; SAVE ON STACK FOR LEAVE EOR #$FF ; ALLOCATE FRAME @@ -1448,22 +1441,22 @@ ENTER INY INX DEY STA (IFP),Y - BNE - + BNE - + LDY #$02 JMP NEXTOP ;* ;* LEAVE FUNCTION ;* -LEAVEX STA ALTRDOFF +LEAVEX STA ALTRDOFF CLI -LEAVE PLA ; DEALLOCATE POOL + FRAME +LEAVE PLA ; DEALLOCATE POOL + FRAME CLC ADC IFPL STA PPL LDA #$00 ADC IFPH STA PPH - PLA ; RESTORE PREVIOUS FRAME + PLA ; RESTORE PREVIOUS FRAME STA IFPL PLA STA IFPH @@ -1475,7 +1468,7 @@ RET LDA IFPL ; DEALLOCATE POOL STA PPL LDA IFPH STA PPH - PLA ; RESTORE PREVIOUS FRAME + PLA ; RESTORE PREVIOUS FRAME STA IFPL PLA STA IFPH diff --git a/src/vmsrc/plvm03.s b/src/vmsrc/plvm03.s index bc82707..4d8f59a 100644 --- a/src/vmsrc/plvm03.s +++ b/src/vmsrc/plvm03.s @@ -218,7 +218,7 @@ _DIVEX INX OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E !WORD LNOT,LOR,LAND,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E - !WORD DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E + !WORD DROP,DUP,PUSHEP,PULLEP,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E !WORD BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,NEXTOP ; 50 52 54 56 58 5A 5C 5E !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E @@ -488,23 +488,16 @@ DUP DEX STA ESTKH,X JMP NEXTOP ;* -;* PUSH FROM EVAL STACK TO CALL STACK +;* PUSH EVAL STACK POINTER TO CALL STACK ;* -PUSH LDA ESTKL,X +PUSHEP TXA PHA - LDA ESTKH,X - PHA -; INX -; JMP NEXTOP - JMP DROP + JMP NEXTOP ;* ;* PULL FROM CALL STACK TO EVAL STACK ;* -PULL DEX - PLA - STA ESTKH,X - PLA - STA ESTKL,X +PULLEP PLA + TAX JMP NEXTOP ;* ;* CONSTANT @@ -702,11 +695,11 @@ LAW +INC_IP ;* ;* STORE VALUE TO ADDRESS ;* -SB LDA ESTKL+1,X +SB LDA ESTKL,X STA TMPL - LDA ESTKH+1,X + LDA ESTKH,X STA TMPH - LDA ESTKL,X + LDA ESTKL+1,X STY IPY LDY #$00 STA (TMP),Y @@ -715,16 +708,16 @@ SB LDA ESTKL+1,X ; INX ; JMP NEXTOP JMP DROP -SW LDA ESTKL+1,X +SW LDA ESTKL,X STA TMPL - LDA ESTKH+1,X + LDA ESTKH,X STA TMPH STY IPY LDY #$00 - LDA ESTKL,X + LDA ESTKL+1,X STA (TMP),Y INY - LDA ESTKH,X + LDA ESTKH+1,X STA (TMP),Y LDY IPY INX diff --git a/src/vmsrc/plvmzp.inc b/src/vmsrc/plvmzp.inc old mode 100644 new mode 100755 index 2e6aebb..fd9bb75 --- a/src/vmsrc/plvmzp.inc +++ b/src/vmsrc/plvmzp.inc @@ -10,9 +10,9 @@ DST = SRC+2 DSTL = DST DSTH = DST+1 ESTKSZ = $20 -XSTK = $A0 -XSTKL = XSTK -XSTKH = XSTK+ESTKSZ/2 +XSTK = $A0 +XSTKL = XSTK +XSTKH = XSTK+ESTKSZ/2 ESTK = $C0 ESTKL = ESTK ESTKH = ESTK+ESTKSZ/2 diff --git a/src/vmsrc/soscmd.pla b/src/vmsrc/soscmd.pla old mode 100644 new mode 100755 index 6abe962..0767d88 --- a/src/vmsrc/soscmd.pla +++ b/src/vmsrc/soscmd.pla @@ -34,13 +34,13 @@ predef loadmod, execmod, lookupstrmod // // System variables. // -word version = $0094 // 00.94 +word version = $0099 // 00.99 word systemflags = 0 byte refcons = 0 byte devcons = 0 word heap = $2000 byte modid = 0 -byte modseg[15] +byte modseg[15] word symtbl, lastsym byte perr, terr, lerr // @@ -108,7 +108,7 @@ word = @modadrstr, @lookupstrmod word = @machidstr, @machid word = @argstr, @cmdptr word = 0 -word syslibsym = @exports +word syslibsym = @exports // // CALL SOS // SYSCALL(CMD, PARAMS) @@ -411,7 +411,7 @@ asm interp STA ESTKH,X RTS end -// +// // A DCI string is one that has the high bit set for every character except the last. // More efficient than C or Pascal strings. // @@ -691,7 +691,7 @@ end // def dev_control(devnum, code, list) byte params[5] - + params.0 = 3 params.1 = devnum params.2 = code @@ -701,7 +701,7 @@ def dev_control(devnum, code, list) end def dev_getnum(name) byte params[4] - + params.0 = 2 params:1 = name params.3 = 0 @@ -710,7 +710,7 @@ def dev_getnum(name) end def dev_info(devnum, name, list, listlen) byte params[7] - + params.0 = 4 params.1 = devnum params:2 = name @@ -724,7 +724,7 @@ end // def seg_request(base, limit, id) byte params[7] - + params.0 = 4 params:1 = base params:3 = limit @@ -735,7 +735,7 @@ def seg_request(base, limit, id) end def seg_find(search, base, limit, pages, id) byte params[10] - + params.0 = 6 params.1 = search params.2 = id @@ -750,7 +750,7 @@ def seg_find(search, base, limit, pages, id) end def seg_release(segnum) byte params[2] - + params.0 = 1 params.1 = segnum perr = syscall($45, @params) @@ -948,7 +948,7 @@ def loadmod(mod) moddep = @header.1 defofst = modsize init = 0 - if rdlen > 4 and header:2 == $DA7E // DAVE = magic number :-) + if rdlen > 4 and header:2 == $DA7F // DAVE+1 = magic number :-) // // This is an EXTended RELocatable (data+bytecode) module. // @@ -985,6 +985,8 @@ def loadmod(mod) refnum = open(@filename, O_READ) rdlen = read(refnum, @header, 128) fin + else + return -69 fin // // Alloc heap space for relocated module (data + bytecode). From 45500004dd165faec5ffa13f2e37b9fadde0eaad Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 1 Jun 2017 12:23:29 -0700 Subject: [PATCH 49/58] On the road to 1.0: optimize MUL/DIV by POW2 --- src/toolsrc/codegen.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index 9d0cfb8..a6bb4d4 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -914,12 +914,13 @@ int crunch_seq(t_opseq *seq) t_opseq *op = seq; int crunched = 0; int freeops = 0; + int shiftcnt; + while (op && (opnext = op->nextop)) { switch (op->code) { case CONST_CODE: - //fprintf(stderr, "CONST -> $%04X", opnext->code); if (op->val == 1) { if (opnext->code == BINARY_CODE(ADD_TOKEN)) @@ -971,6 +972,28 @@ int crunch_seq(t_opseq *seq) op->code = SAW_CODE; freeops = 1; break; + case BINARY_CODE(MUL_TOKEN): + for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + { + if (op->val == (1 << shiftcnt)) + { + op->val = shiftcnt; + opnext->code = BINARY_CODE(SHL_TOKEN); + break; + } + } + break; + case BINARY_CODE(DIV_TOKEN): + for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + { + if (op->val == (1 << shiftcnt)) + { + op->val = shiftcnt; + opnext->code = BINARY_CODE(SHR_TOKEN); + break; + } + } + break; case CONST_CODE: // Collapse constant operation if ((opnextnext = opnext->nextop)) switch (opnextnext->code) From 3415077a2ad4c29b4e574e77034b0e10e98a8642 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Thu, 1 Jun 2017 13:07:52 -0700 Subject: [PATCH 50/58] On the way to 1.0: Document multi-value assignment/return values --- README.md | 211 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 125 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 1464df4..d5affda 100755 --- a/README.md +++ b/README.md @@ -17,83 +17,83 @@ Different projects have led to the architecture of PLASMA, most notably Apple Pa - [Build Environment](#build-environment) - - [acme Cross-Assembler](#acme-cross-assembler) - - [PLASMA Source](#plasma-source) - - [Portable VM](#portable-vm) - - [Target VM](#target-vm) + - [acme Cross-Assembler](#acme-cross-assembler) + - [PLASMA Source](#plasma-source) + - [Portable VM](#portable-vm) + - [Target VM](#target-vm) - [Tutorial](#tutorial) - - [PLASMA Compiler/Assembler](#plasma-compilerassembler) - - [PLASMA Modules](#plasma-modules) - - [Data Types](#data-types) - - [Obligatory 'Hello World'](#obligatory-hello-world) - - [Character Case](#character-case) - - [Comments](#comments) - - [Numbers](#numbers) - - [Characters](#characters) - - [Strings](#strings) - - [Organization of a PLASMA Source File](#organization-of-a-plasma-source-file) - - [Module Dependencies](#module-dependencies) - - [File Inclusion](#file-inclusion) - - [Predefined Functions](#predefined-functions) - - [Constant Declarations](#constant-declarations) - - [Structure Declarations](#structure-declarations) - - [Global Data & Variables Declarations](#global-data-variables-declarations) - - [Function Definitions](#function-definitions) - - [Statements and Expressions](#statements-and-expressions) - - [Exported Declarations](#exported-declarations) - - [Module Main Initialization Function](#module-main-initialization-function) - - [Module Done](#module-done) - - [Runtime](#runtime) + - [PLASMA Compiler/Assembler](#plasma-compilerassembler) + - [PLASMA Modules](#plasma-modules) + - [Data Types](#data-types) + - [Obligatory 'Hello World'](#obligatory-hello-world) + - [Character Case](#character-case) + - [Comments](#comments) + - [Numbers](#numbers) + - [Characters](#characters) + - [Strings](#strings) + - [Organization of a PLASMA Source File](#organization-of-a-plasma-source-file) + - [Module Dependencies](#module-dependencies) + - [File Inclusion](#file-inclusion) + - [Predefined Functions](#predefined-functions) + - [Constant Declarations](#constant-declarations) + - [Structure Declarations](#structure-declarations) + - [Global Data & Variables Declarations](#global-data-variables-declarations) + - [Function Definitions](#function-definitions) + - [Statements and Expressions](#statements-and-expressions) + - [Exported Declarations](#exported-declarations) + - [Module Main Initialization Function](#module-main-initialization-function) + - [Module Done](#module-done) + - [Runtime](#runtime) - [Reference](#reference) - - [Decimal and Hexadecimal Numbers](#decimal-and-hexadecimal-numbers) - - [Character and String Literals](#character-and-string-literals) - - [In-line String Literals](#in-line-string-literals) - - [Words](#words) - - [Bytes](#bytes) - - [Addresses](#addresses) - - [Arrays](#arrays) - - [Type Overrides](#type-overrides) - - [Multi-Dimensional Arrays](#multi-dimensional-arrays) - - [Offsets (Structure Elements)](#offsets-structure-elements) - - [Defining Structures](#defining-structures) - - [Pointers](#pointers) - - [Pointer Dereferencing](#pointer-dereferencing) - - [Addresses of Data/Code](#addresses-of-datacode) - - [Function Pointers](#function-pointers) - - [Function Definitions](#function-definitions) - - [Expressions and Statements](#expressions-and-statements) - - [Address Operators](#address-operators) - - [Arithmetic, Bitwise, and Logical Operators](#arithmetic-bitwise-and-logical-operators) - - [Assignment](#assignment) - - [Empty Assignments](#empty-assignments) - - [Increment and Decrement](#increment-and-decrement) - - [Control Flow](#control-flow) - - [CALL](#call) - - [RETURN](#return) - - [IF/[ELSIF]/[ELSE]/FIN](#ifelsifelsefin) - - [WHEN/IS/[OTHERWISE]/WEND](#whenisotherwisewend) - - [FOR \ [STEP]/NEXT](#for-todownto-stepnext) - - [WHILE/LOOP](#whileloop) - - [REPEAT/UNTIL](#repeatuntil) - - [CONTINUE](#continue) - - [BREAK](#break) + - [Decimal and Hexadecimal Numbers](#decimal-and-hexadecimal-numbers) + - [Character and String Literals](#character-and-string-literals) + - [In-line String Literals](#in-line-string-literals) + - [Words](#words) + - [Bytes](#bytes) + - [Addresses](#addresses) + - [Arrays](#arrays) + - [Type Overrides](#type-overrides) + - [Multi-Dimensional Arrays](#multi-dimensional-arrays) + - [Offsets (Structure Elements)](#offsets-structure-elements) + - [Defining Structures](#defining-structures) + - [Pointers](#pointers) + - [Pointer Dereferencing](#pointer-dereferencing) + - [Addresses of Data/Code](#addresses-of-datacode) + - [Function Pointers](#function-pointers) + - [Function Definitions](#function-definitions) + - [Expressions and Statements](#expressions-and-statements) + - [Address Operators](#address-operators) + - [Arithmetic, Bitwise, and Logical Operators](#arithmetic-bitwise-and-logical-operators) + - [Assignment](#assignment) + - [Empty Assignments](#empty-assignments) + - [Increment and Decrement](#increment-and-decrement) + - [Control Flow](#control-flow) + - [CALL](#call) + - [RETURN](#return) + - [IF/[ELSIF]/[ELSE]/FIN](#ifelsifelsefin) + - [WHEN/IS/[OTHERWISE]/WEND](#whenisotherwisewend) + - [FOR \ [STEP]/NEXT](#for-todownto-stepnext) + - [WHILE/LOOP](#whileloop) + - [REPEAT/UNTIL](#repeatuntil) + - [CONTINUE](#continue) + - [BREAK](#break) - [Advanced Topics](#advanced-topics) - - [Code Optimizations](#code-optimizations) - - [Functions Without Parameters Or Local Variables](#functions-without-parameters-or-local-variables) - - [Return Values](#return-values) - - [Native Assembly Functions](#native-assembly-functions) + - [Code Optimizations](#code-optimizations) + - [Functions Without Parameters Or Local Variables](#functions-without-parameters-or-local-variables) + - [Return Values](#return-values) + - [Native Assembly Functions](#native-assembly-functions) - [Implementation](#implementation) - - [A New Approach](#a-new-approach) - - [The Virtual Machine](#the-virtual-machine) - - [The Stacks](#the-stacks) - - [Evaluation Stack](#evaluation-stack) - - [Call Stack](#call-stack) - - [Local Frame Stack](#local-frame-stack) - - [Local String Pool](#local-string-pool) - - [The Bytecodes](#the-bytecodes) - - [Apple I PLASMA](#apple-i-plasma) - - [Apple II PLASMA](#apple-ii-plasma) - - [Apple III PLASMA](#apple-iii-plasma) + - [A New Approach](#a-new-approach) + - [The Virtual Machine](#the-virtual-machine) + - [The Stacks](#the-stacks) + - [Evaluation Stack](#evaluation-stack) + - [Call Stack](#call-stack) + - [Local Frame Stack](#local-frame-stack) + - [Local String Pool](#local-string-pool) + - [The Bytecodes](#the-bytecodes) + - [Apple I PLASMA](#apple-i-plasma) + - [Apple II PLASMA](#apple-ii-plasma) + - [Apple III PLASMA](#apple-iii-plasma) - [Links](#links) @@ -365,7 +365,29 @@ byte[64] txtfile = "UNTITLED" ### Function Definitions -Functions are defined after all constants, variables and data. Function definitions can be `export`ed for inclusion in other modules and can be forward declared with a `predef` type in the constant and variable declarations. Functions can take parameters, passed on the evaluation stack, then copied to the local frame for easy access. They can have their own variable declarations, however, unlike the global declarations, no data can be predeclared - only storage space. A local frame is built for every function invocation and there is also a limit of 254 bytes of local storage. Each parameter takes two bytes of local storage, plus two bytes for the previous frame pointer. If a function has no parameters or local variables, no local frame will be created, improving performance. Functions always return a value; a function can specify a value to return or, if no return value is specified, a default of 0 will be returned. +Functions are defined after all constants, variables and data. Function definitions can be `export`ed for inclusion in other modules and can be forward declared with a `predef` type in the constant and variable declarations. Functions can take parameters, passed on the evaluation stack, then copied to the local frame for easy access. They can have their own variable declarations, however, unlike the global declarations, no data can be predeclared - only storage space. A local frame is built for every function invocation and there is also a limit of 254 bytes of local storage. Each parameter takes two bytes of local storage, plus two bytes for the previous frame pointer. If a function has no parameters or local variables, no local frame will be created, improving performance. Functions always return a single value by default. +``` +def myfunc(a, b) // Two parameters and defaults to one returned value +``` +The number of values to return can be set by appending the number of values after the function definition with the '#' syntax, such as: + +``` +def myfuncA(a, b)#3 // Two parameters and three returned values +``` +A definition with no parameters but with return values can be written as: +``` +def myfuncB#2 // No parameters and two returned values +``` +A pre-defined definition should include the same number of parameters and return values as the definition: +``` +predef myfuncA(a, b)#3 +``` +A value used as a function pointer doesn't have the parameter/return value count associated with it. It can be overridden in-line: +``` +word funcptr = @myfuncA +funcptr(2, 4)#3 +``` +If fewer values are returned, the remaining values will be padded with zero. It is an error to return more values than specified. Returning zero paramaters is ok, and can save some stack clean-up if the definition is called stand-alone (i.e. as a procedure). Note: there is no mechanism to ensure caller and callee agree on the number of parameters. Historically, programmers have used Hungarian Notation (http://en.wikipedia.org/wiki/Hungarian_notation) to embed the parameter number and type in the function name itself. This is a notational aid; the compiler enforces nothing. @@ -394,6 +416,23 @@ byte numchars numchars = 0 ``` +Multi-value assignments are written with lvalues separated by commas, and the same number of rvalues separated by commas: +``` +a, b, c = 2, 4, 6 +``` +Definitions can return values that contribute to the rvalue count: +``` +def myfuncC(p1, p2)#2 + return p1+p2, p1-p2 +end + +a, b, c = 2, myfuncC(6, 7) // Note: myfuncA returns 2 values +``` +A quick way to swap variables could be written: +``` +a, b = b, a +``` + Expressions can be built up with constants, variables, function calls, addresses, and pointers/arrays. Comparison operators evaluate to 0 or -1 instead of the more traditional 0 or 1. The use of -1 allows binary operations to be applied to other non-zero values and still retain a non-zero result. Any conditional tests check only for zero and non-zero values. There are four basic types of data that can be manipulated: constants, variables, addresses, and functions. Memory can only be read or written as either a byte or a word. Bytes are unsigned 8-bit quantities, words are signed 16-bit quantities. Everything on the evaluation stack is treated as a word. Other than that, any value can be treated as a pointer, address, function, character, integer, etc. There are convenience operations in PLASMA to easily manipulate addresses and expressions as pointers, arrays, structures, functions, or combinations thereof. If a variable is declared as a byte, it can be accessed as a simple, single dimension byte array by using brackets to indicate the offset. Any expression can calculate the indexed offset. A word variable can be accessed as a word array in the same fashion. In order to access expressions or constants as arrays, a type identifier has to be inserted before the brackets. a `.` character denotes a byte type, a `:` character denotes a word type. Along with brackets to calculate an indexed offset, a constant can be used after the `.` or `:` and will be added to the base address. The constant can be a defined const to allow for structure style syntax. If the offset is a known constant, using the constant offset is a much more efficient way to address the elements over an array index. Multidimensional arrays are treated as arrays of array pointers. @@ -721,13 +760,13 @@ word = $2080,$2480,$2880,$2C80,$3080,$3480,$3880,$3C80 ``` def hgrfill(val) - byte yscan, xscan + byte yscan, xscan - for yscan = 0 to 191 - for xscan = 0 to 19 - hgrscan:[yscan, xscan] = val - next - next + for yscan = 0 to 191 + for xscan = 0 to 19 + hgrscan:[yscan, xscan] = val + next + next end ``` @@ -735,13 +774,13 @@ Every array dimension except the last is a pointer to another array of pointers, ``` def hgrfill(val) - byte yscan, xscan + byte yscan, xscan - for yscan = 0 to 191 - for xscan = 0 to 39 - hgrscan.[yscan, xscan] = val - next - next + for yscan = 0 to 191 + for xscan = 0 to 39 + hgrscan.[yscan, xscan] = val + next + next end ``` From 6cdbcdd0599d7ae70ea65a2928ff0ebe67b82a39 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 1 Jun 2017 14:06:44 -0700 Subject: [PATCH 51/58] On the road to 1.0: Update multiple return value description --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index d5affda..78c9799 100755 --- a/README.md +++ b/README.md @@ -387,9 +387,7 @@ A value used as a function pointer doesn't have the parameter/return value count word funcptr = @myfuncA funcptr(2, 4)#3 ``` -If fewer values are returned, the remaining values will be padded with zero. It is an error to return more values than specified. Returning zero paramaters is ok, and can save some stack clean-up if the definition is called stand-alone (i.e. as a procedure). - -Note: there is no mechanism to ensure caller and callee agree on the number of parameters. Historically, programmers have used Hungarian Notation (http://en.wikipedia.org/wiki/Hungarian_notation) to embed the parameter number and type in the function name itself. This is a notational aid; the compiler enforces nothing. +If fewer values are returned, the remaining values will be padded with zero. It is an error to return more values than specified. Returning zero values is ok, and can save some stack clean-up if the definition is called stand-alone (i.e. as a procedure). After functions are defined, the main code for the module follows. The main code will be executed as soon as the module is loaded. For library modules, this is a good place to do any runtime initialization, before any of the exported functions are called. The last statement in the module must be done, or else a compile error is issued. From f1c11d6b972cb729612353323c09185eeb471bf0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 2 Jun 2017 06:39:25 -0700 Subject: [PATCH 52/58] On the road to 1.0: clarify zero return value definitions --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 78c9799..ebe3449 100755 --- a/README.md +++ b/README.md @@ -387,7 +387,7 @@ A value used as a function pointer doesn't have the parameter/return value count word funcptr = @myfuncA funcptr(2, 4)#3 ``` -If fewer values are returned, the remaining values will be padded with zero. It is an error to return more values than specified. Returning zero values is ok, and can save some stack clean-up if the definition is called stand-alone (i.e. as a procedure). +If fewer values are returned, the remaining values will be padded with zero. It is an error to return more values than specified. Definitions returning zero values are ok and can save some stack clean-up if the definitions are called stand-alone (i.e. as a procedure). After functions are defined, the main code for the module follows. The main code will be executed as soon as the module is loaded. For library modules, this is a good place to do any runtime initialization, before any of the exported functions are called. The last statement in the module must be done, or else a compile error is issued. @@ -424,7 +424,7 @@ def myfuncC(p1, p2)#2 return p1+p2, p1-p2 end -a, b, c = 2, myfuncC(6, 7) // Note: myfuncA returns 2 values +a, b, c = 2, myfuncC(6, 7) // Note: myfuncC returns 2 values ``` A quick way to swap variables could be written: ``` From 47ed2014e30d2a6891d87f6328aeffecbe5419f4 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 3 Jun 2017 08:08:30 -0700 Subject: [PATCH 53/58] On the road to 1.0: source code cleanup --- src/toolsrc/lex.c | 72 +++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index 77ae0ca..8c72b0c 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2015 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1 + * Copyright (C) 2015 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ @@ -37,31 +37,31 @@ t_token keywords[] = { DEFAULT_TOKEN, 'O', 'T', 'H', 'E', 'R', 'W', 'I', 'S', 'E', ENDCASE_TOKEN, 'W', 'E', 'N', 'D', FOR_TOKEN, 'F', 'O', 'R', - TO_TOKEN, 'T', 'O', - DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O', - STEP_TOKEN, 'S', 'T', 'E', 'P', + TO_TOKEN, 'T', 'O', + DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O', + STEP_TOKEN, 'S', 'T', 'E', 'P', NEXT_TOKEN, 'N', 'E', 'X', 'T', REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T', UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L', BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K', - CONTINUE_TOKEN, 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'E', - ASM_TOKEN, 'A', 'S', 'M', - DEF_TOKEN, 'D', 'E', 'F', - EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T', - IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T', + CONTINUE_TOKEN, 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'E', + ASM_TOKEN, 'A', 'S', 'M', + DEF_TOKEN, 'D', 'E', 'F', + EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T', + IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T', INCLUDE_TOKEN, 'I', 'N', 'C', 'L', 'U', 'D', 'E', RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N', END_TOKEN, 'E', 'N', 'D', - DONE_TOKEN, 'D', 'O', 'N', 'E', + DONE_TOKEN, 'D', 'O', 'N', 'E', LOGIC_NOT_TOKEN, 'N', 'O', 'T', LOGIC_AND_TOKEN, 'A', 'N', 'D', - LOGIC_OR_TOKEN, 'O', 'R', + LOGIC_OR_TOKEN, 'O', 'R', BYTE_TOKEN, 'B', 'Y', 'T', 'E', - WORD_TOKEN, 'W', 'O', 'R', 'D', + WORD_TOKEN, 'W', 'O', 'R', 'D', CONST_TOKEN, 'C', 'O', 'N', 'S', 'T', STRUC_TOKEN, 'S', 'T', 'R', 'U', 'C', PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F', - SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S', + SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S', EOL_TOKEN }; @@ -428,8 +428,11 @@ int next_line(void) int len; t_token token; char* new_filename; - if (inputfile == NULL) { - // First-time init + if (inputfile == NULL) + { + /* + * First-time init + */ inputfile = stdin; filename = (char*) ""; } @@ -442,11 +445,17 @@ int next_line(void) { statement = inputline; scanpos = inputline; - // Read next line from the current file, and strip newline from the end. - if (fgets(inputline, 512, inputfile) == NULL) { + /* + * Read next line from the current file, and strip newline from the end. + */ + if (fgets(inputline, 512, inputfile) == NULL) + { inputline[0] = 0; - // At end of file, return to previous file if any, else return EOF_TOKEN - if (outer_inputfile != NULL) { + /* + * At end of file, return to previous file if any, else return EOF_TOKEN + */ + if (outer_inputfile != NULL) + { fclose(inputfile); free(filename); inputfile = outer_inputfile; @@ -454,7 +463,8 @@ int next_line(void) lineno = outer_lineno - 1; // -1 because we're about to incr again outer_inputfile = NULL; } - else { + else + { scantoken = EOF_TOKEN; return EOF_TOKEN; } @@ -467,15 +477,20 @@ int next_line(void) printf("; %s: %04d: %s\n", filename, lineno, inputline); } token = scan(); - // Handle single level of file inclusion - if (token == INCLUDE_TOKEN) { + /* + * Handle single level of file inclusion + */ + if (token == INCLUDE_TOKEN) + { token = scan(); - if (token != STRING_TOKEN) { + if (token != STRING_TOKEN) + { parse_error("Missing include filename"); scantoken = EOF_TOKEN; return EOF_TOKEN; } - if (outer_inputfile != NULL) { + if (outer_inputfile != NULL) + { parse_error("Only one level of includes allowed"); scantoken = EOF_TOKEN; return EOF_TOKEN; @@ -487,7 +502,8 @@ int next_line(void) strncpy(new_filename, (char*)constval, tokenlen-2); new_filename[tokenlen-2] = 0; inputfile = fopen(new_filename, "r"); - if (inputfile == NULL) { + if (inputfile == NULL) + { parse_error("Error opening include file"); scantoken = EOF_TOKEN; return EOF_TOKEN; From def57dc26323dbac62c5387f3a2ac2f2fe21bf9a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 6 Jun 2017 12:27:59 -0700 Subject: [PATCH 54/58] Fix some pointer to pointer problems and scan_rewind with string quotes --- src/toolsrc/lex.c | 11 +++++++---- src/toolsrc/parse.c | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index 8c72b0c..cded50d 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -234,16 +234,18 @@ t_token scan(void) scanpos += 4; } } - else if (scanpos[0] == '\"') + else if ((scanpos[0] & 0x7F) == '\"') // Hack for string quote char in case we have to rewind later { - char *scanshift; + char *scanshift, quotechar; int scanoffset; /* * String constant. */ + quotechar = scanpos[0]; + *scanpos |= 0x80; // Set high bit in case of rewind scantoken = STRING_TOKEN; constval = (long)++scanpos; - while (*scanpos && *scanpos != '\"') + while (*scanpos && *scanpos != quotechar) { if (*scanpos == '\\') { @@ -288,11 +290,12 @@ t_token scan(void) } scanpos++; } - if (!*scanpos++) + if (!*scanpos) { parse_error("Unterminated string"); return (-1); } + *scanpos++ |= 0x80; // Set high bit in case of rewind } else { diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index a9aeb2f..d3191cd 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -501,7 +501,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth) if (stackdepth) *stackdepth = cfnvals; cfnvals = 1; - type &= ~FUNC_TYPE; + type &= ~(FUNC_TYPE | VAR_TYPE); } else if (scantoken == OPEN_BRACKET_TOKEN) { @@ -556,7 +556,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth) *stackdepth = cfnvals; type &= ~FUNC_TYPE; } - else if (type & VAR_TYPE) + else if (type & (VAR_TYPE | PTR_TYPE)) { /* * Pointer dereference From d7d50f3d373a7603918d14d797c4df348f76c4bb Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 6 Jun 2017 13:02:51 -0700 Subject: [PATCH 55/58] Remove 8-bit bunch license that shouldn't be there. --- src/toolsrc/lex.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index cded50d..7319f68 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -1,13 +1,3 @@ -/* - * Copyright (C) 2015 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1 - * (the "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at . - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - #include #include #include From 7d35fd77260d18b77f0a24433960521ce19cc573 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 7 Jun 2017 14:27:52 -0700 Subject: [PATCH 56/58] Clean up scan_rewind string parsing and add branch optimizations --- src/toolsrc/codegen.c | 107 ++++++++++++++++++++++++++++++------------ src/toolsrc/codegen.h | 11 +++-- src/toolsrc/lex.c | 65 +++++++++++++------------ src/toolsrc/parse.c | 29 +++++++----- 4 files changed, 136 insertions(+), 76 deletions(-) diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index a6bb4d4..9177565 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -473,7 +473,7 @@ void emit_idconst(char *name, int value) int emit_data(int vartype, int consttype, long constval, int constsize) { int datasize, i; - char *str; + unsigned char *str; if (consttype == 0) { datasize = constsize; @@ -481,9 +481,10 @@ int emit_data(int vartype, int consttype, long constval, int constsize) } else if (consttype & STRING_TYPE) { - datasize = constsize; - str = (char *)constval; - printf("\t%s\t$%02X\n", DB, --constsize); + str = (unsigned char *)constval; + constsize = *str++; + datasize = constsize + 1; + printf("\t%s\t$%02X\n", DB, constsize); while (constsize-- > 0) { printf("\t%s\t$%02X", DB, *str++); @@ -546,10 +547,10 @@ void emit_const(int cval) else printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval); } -void emit_conststr(long conststr, int strsize) +void emit_conststr(long conststr) { printf("\t%s\t$2E\t\t\t; CS\n", DB); - emit_data(0, STRING_TYPE, conststr, strsize); + emit_data(0, STRING_TYPE, conststr, 0); } void emit_lb(void) { @@ -908,14 +909,14 @@ void release_seq(t_opseq *seq) /* * Crunch sequence (peephole optimize) */ -int crunch_seq(t_opseq *seq) +int crunch_seq(t_opseq **seq) { t_opseq *opnext, *opnextnext; - t_opseq *op = seq; + t_opseq *op = *seq; int crunched = 0; int freeops = 0; int shiftcnt; - + while (op && (opnext = op->nextop)) { switch (op->code) @@ -972,26 +973,40 @@ int crunch_seq(t_opseq *seq) op->code = SAW_CODE; freeops = 1; break; - case BINARY_CODE(MUL_TOKEN): - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + case BRFALSE_CODE: + if (op->val) { - if (op->val == (1 << shiftcnt)) - { - op->val = shiftcnt; - opnext->code = BINARY_CODE(SHL_TOKEN); - break; - } + opnextnext = opnext->nextop; // Remove never taken branch + if (op == *seq) + *seq = opnextnext; + opnext->nextop = NULL; + release_seq(op); + opnext = opnextnext; + crunched = 1; + } + else + { + op->code = BRNCH_CODE; // Always taken branch + op->tag = opnext->tag; + freeops = 1; } break; - case BINARY_CODE(DIV_TOKEN): - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + case BRTRUE_CODE: + if (!op->val) { - if (op->val == (1 << shiftcnt)) - { - op->val = shiftcnt; - opnext->code = BINARY_CODE(SHR_TOKEN); - break; - } + opnextnext = opnext->nextop; // Remove never taken branch + if (op == *seq) + *seq = opnextnext; + opnext->nextop = NULL; + release_seq(op); + opnext = opnextnext; + crunched = 1; + } + else + { + op->code = BRNCH_CODE; // Always taken branch + op->tag = opnext->tag; + freeops = 1; } break; case CONST_CODE: // Collapse constant operation @@ -1072,6 +1087,28 @@ int crunch_seq(t_opseq *seq) break; } break; // CONST_CODE + case BINARY_CODE(MUL_TOKEN): + for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + { + if (op->val == (1 << shiftcnt)) + { + op->val = shiftcnt; + opnext->code = BINARY_CODE(SHL_TOKEN); + break; + } + } + break; + case BINARY_CODE(DIV_TOKEN): + for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + { + if (op->val == (1 << shiftcnt)) + { + op->val = shiftcnt; + opnext->code = BINARY_CODE(SHR_TOKEN); + break; + } + } + break; } break; // CONST_CODE case LADDR_CODE: @@ -1212,11 +1249,10 @@ t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2) int emit_seq(t_opseq *seq) { t_opseq *op; + int emitted = 0; - if (!seq) - return (0); if (outflags & OPTIMIZE) - while (crunch_seq(seq)); + while (crunch_seq(&seq)); while (seq) { op = seq; @@ -1255,7 +1291,7 @@ int emit_seq(t_opseq *seq) emit_const(op->val); break; case STR_CODE: - emit_conststr(op->val, op->offsz); + emit_conststr(op->val); break; case LB_CODE: emit_lb(); @@ -1329,15 +1365,26 @@ int emit_seq(t_opseq *seq) case DUP_CODE: emit_dup(); break; + break; case PUSH_EXP_CODE: emit_push_exp(); break; case PULL_EXP_CODE: emit_pull_exp(); break; + case BRNCH_CODE: + emit_brnch(op->tag); + break; + case BRFALSE_CODE: + emit_brfls(op->tag); + break; + case BRTRUE_CODE: + emit_brtru(op->tag); + break; default: return (0); } + emitted++; seq = seq->nextop; /* * Free this op @@ -1345,5 +1392,5 @@ int emit_seq(t_opseq *seq) op->nextop = freeop_lst; freeop_lst = op; } - return (1); + return (emitted); } diff --git a/src/toolsrc/codegen.h b/src/toolsrc/codegen.h index f69c96b..b25f0b4 100755 --- a/src/toolsrc/codegen.h +++ b/src/toolsrc/codegen.h @@ -61,11 +61,14 @@ typedef struct _opseq { #define DUP_CODE 0x0319 #define PUSH_EXP_CODE 0x031A #define PULL_EXP_CODE 0x031B +#define BRNCH_CODE 0x031C +#define BRFALSE_CODE 0x031D +#define BRTRUE_CODE 0x031E #define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0) #define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0) #define gen_const(seq,val) gen_seq(seq,CONST_CODE,val,0,0,0) -#define gen_str(seq,str,len) gen_seq(seq,STR_CODE,str,0,len,0) +#define gen_str(seq,str) gen_seq(seq,STR_CODE,str,0,0,0) #define gen_lcladr(seq,idx) gen_seq(seq,LADDR_CODE,0,0,idx,0) #define gen_gbladr(seq,tag,typ) gen_seq(seq,GADDR_CODE,0,tag,0,typ) #define gen_idxb(seq) gen_seq(seq,ADD_CODE,0,0,0,0) @@ -78,6 +81,8 @@ typedef struct _opseq { #define gen_pushexp(seq) gen_seq(seq,PUSH_EXP_CODE,0,0,0,0) #define gen_pullexp(seq) gen_seq(seq,PULL_EXP_CODE,0,0,0,0) #define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0) +#define gen_brfls(seq,tag) gen_seq(seq,BRFALSE_CODE,0,tag,0,0) +#define gen_brtru(seq,tag) gen_seq(seq,BRTRUE_CODE,0,tag,0,0) void emit_flags(int flags); void emit_header(void); @@ -94,7 +99,7 @@ void emit_idconst(char *name, int value); int emit_data(int vartype, int consttype, long constval, int constsize); void emit_codetag(int tag); void emit_const(int cval); -void emit_conststr(long conststr, int strsize); +void emit_conststr(long conststr); void emit_lb(void); void emit_lw(void); void emit_llb(int index); @@ -137,7 +142,7 @@ void emit_start(void); void emit_rld(void); void emit_esd(void); void release_seq(t_opseq *seq); -int crunch_seq(t_opseq *seq); +int crunch_seq(t_opseq **seq); t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type); t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2); int emit_seq(t_opseq *seq); diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index 7319f68..06d87e4 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -5,7 +5,7 @@ #include #include "plasm.h" -char *statement, *tokenstr, *scanpos = (char*) ""; +char *statement, *tokenstr, *scanpos = "", *strpos = ""; t_token scantoken, prevtoken; int tokenlen; long constval; @@ -224,68 +224,68 @@ t_token scan(void) scanpos += 4; } } - else if ((scanpos[0] & 0x7F) == '\"') // Hack for string quote char in case we have to rewind later + else if (scanpos[0] == '\"') // Hack for string quote char in case we have to rewind later { - char *scanshift, quotechar; int scanoffset; /* * String constant. */ - quotechar = scanpos[0]; - *scanpos |= 0x80; // Set high bit in case of rewind - scantoken = STRING_TOKEN; - constval = (long)++scanpos; - while (*scanpos && *scanpos != quotechar) + scantoken = STRING_TOKEN; + constval = (long)strpos++; + scanpos++; + while (*scanpos && *scanpos != '\"') { if (*scanpos == '\\') { - scanoffset = 1; + scanoffset = 2; switch (scanpos[1]) { case 'n': - *scanpos = 0x0D; + *strpos++ = 0x0D; break; case 'r': - *scanpos = 0x0A; + *strpos++ = 0x0A; break; case 't': - *scanpos = '\t'; + *strpos++ = '\t'; break; case '\'': - *scanpos = '\''; + *strpos++ = '\''; break; case '\"': - *scanpos = '\"'; + *strpos++ = '\"'; break; case '\\': - *scanpos = '\\'; + *strpos++ = '\\'; break; case '0': - *scanpos = '\0'; + *strpos++ = '\0'; break; case '$': if (hexdigit(scanpos[2]) < 0 || hexdigit(scanpos[3]) < 0) { parse_error("Bad string constant"); return (-1); } - *scanpos = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]); - scanoffset = 3; + *strpos++ = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]); + scanoffset = 4; break; default: parse_error("Bad string constant"); return (-1); } - for (scanshift = scanpos + 1; *scanshift; scanshift++) - scanshift[0] = scanshift[scanoffset]; + scanpos += scanoffset; } - scanpos++; + else + *strpos++ = *scanpos++; } if (!*scanpos) { parse_error("Unterminated string"); return (-1); } - *scanpos++ |= 0x80; // Set high bit in case of rewind + *((unsigned char *)constval) = (long)strpos - constval - 1; + *strpos++ = '\0'; + scanpos++; } else { @@ -404,30 +404,34 @@ void scan_rewind(char *backptr) } int scan_lookahead(void) { - char *backpos = scanpos; - char *backstr = tokenstr; + char *backscan = scanpos; + char *backtkn = tokenstr; + char *backstr = strpos; int prevtoken = scantoken; - int prevlen = tokenlen; + int prevlen = tokenlen; int look = scan(); - scanpos = backpos; - tokenstr = backstr; + scanpos = backscan; + tokenstr = backtkn; + strpos = backstr; scantoken = prevtoken; tokenlen = prevlen; return (look); } char inputline[512]; +char conststr[1024]; int next_line(void) { int len; t_token token; char* new_filename; + strpos = conststr; if (inputfile == NULL) { /* * First-time init */ inputfile = stdin; - filename = (char*) ""; + filename = ""; } if (*scanpos == ';') { @@ -491,9 +495,8 @@ int next_line(void) outer_inputfile = inputfile; outer_filename = filename; outer_lineno = lineno; - new_filename = (char*) malloc(tokenlen-1); - strncpy(new_filename, (char*)constval, tokenlen-2); - new_filename[tokenlen-2] = 0; + new_filename = (char *) malloc(*((unsigned char *)constval) + 1); + strncpy(new_filename, (char *)(constval + 1), *((unsigned char *)constval) + 1); inputfile = fopen(new_filename, "r"); if (inputfile == NULL) { diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index d3191cd..943de13 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -220,7 +220,7 @@ int parse_constval(void) case CLOSE_PAREN_TOKEN: break; case STRING_TOKEN: - size = tokenlen - 1; + size = 1; value = constval; type = STRING_TYPE; if (mod) @@ -412,7 +412,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth) /* * This is a special case. Just emit the string and return */ - codeseq = gen_str(codeseq, constval, tokenlen - 1); + codeseq = gen_str(codeseq, constval); scan(); return (codeseq); } @@ -487,7 +487,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth) } else scan_rewind(tokenstr); - if (cfnparms && (cfnparms != value)) + if ((type & FUNC_TYPE) && (cfnparms != value)) parse_warn("Parameter count mismatch"); if (stackdepth) *stackdepth = cfnvals + cfnparms - value; @@ -766,6 +766,7 @@ int parse_stmnt(void) int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of; int type, addr, step, cfnvals; char *idptr; + t_opseq *seq; /* * Optimization for last function LEAVE and OF clause. @@ -775,14 +776,15 @@ int parse_stmnt(void) switch (scantoken) { case IF_TOKEN: - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } tag_else = tag_new(BRANCH_TYPE); tag_endif = tag_new(BRANCH_TYPE); - emit_brfls(tag_else); + seq = gen_brfls(seq, tag_else); + emit_seq(seq); scan(); do { @@ -791,13 +793,14 @@ int parse_stmnt(void) break; emit_brnch(tag_endif); emit_codetag(tag_else); - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } tag_else = tag_new(BRANCH_TYPE); - emit_brfls(tag_else); + seq = gen_brfls(seq, tag_else); + emit_seq(seq); } while (1); if (scantoken == ELSE_TOKEN) { @@ -826,13 +829,14 @@ int parse_stmnt(void) tag_prevbrk = break_tag; break_tag = tag_wend; emit_codetag(tag_while); - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } - emit_brfls(tag_wend); - while (parse_stmnt()) next_line(); + seq = gen_brfls(seq, tag_wend); + emit_seq(seq); + while (parse_stmnt()) next_line(); if (scantoken != LOOP_TOKEN) { parse_error("Missing WHILE/END"); @@ -859,12 +863,13 @@ int parse_stmnt(void) } emit_codetag(cont_tag); cont_tag = tag_prevcnt; - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } - emit_brfls(tag_repeat); + seq = gen_brfls(seq, tag_repeat); + emit_seq(seq); emit_codetag(break_tag); break_tag = tag_prevbrk; break; From 92535477ff956410c8a62be541db19c5c2348613 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 7 Jun 2017 17:41:50 -0700 Subject: [PATCH 57/58] Optimize NOT before branch --- src/samplesrc/test.pla | 14 ++++++++++---- src/toolsrc/codegen.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/samplesrc/test.pla b/src/samplesrc/test.pla index 7a76576..92fedc7 100755 --- a/src/samplesrc/test.pla +++ b/src/samplesrc/test.pla @@ -32,17 +32,18 @@ byte constr = "Constant expression = " byte[] offsets = "Structure offsets:" word array[] = 1, 10, 100, 1000, 10000 word ptr -byte spaces = " " // // Define functions. // def tens(start) - word i + word i, pptr + i = start + pptr = @print repeat print:hex(i) - print:str(@spaces) - print:dec(i) + print:str(" ") + pptr=>dec(i) print:newln() i = i / 10 until i == 0 @@ -76,10 +77,15 @@ def nums(range) puti(array[1]);putln end export def main(range) + byte a + a = 10 + nums(*range) tens(*range*10) ascii putln + puts("10 * 8 = "); puti(a * 8); putln + puts("10 / 2 = "); puti(a / 2); putln puts(@hello) when MACHID & $C8 is $08 diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index 9177565..46ccba5 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -1187,6 +1187,21 @@ int crunch_seq(t_opseq **seq) break; } break; // GADDR_CODE + case LOGIC_NOT_CODE: + switch (opnext->code) + { + case BRFALSE_CODE: + op->code = BRTRUE_CODE; + op->tag = opnext->tag; + freeops = 1; + break; + case BRTRUE_CODE: + op->code = BRFALSE_CODE; + op->tag = opnext->tag; + freeops = 1; + break; + } + break; // LOGIC_NOT_CODE } // // Free up crunched ops From 0b95baaefcc71943635bf61723d8fdc48b4a8971 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Wed, 7 Jun 2017 19:26:03 -0700 Subject: [PATCH 58/58] Fix predef paramaters, multiple per line, and asm defs with parameters --- SANDBOX.PO | Bin 143360 -> 143360 bytes src/makefile | 10 ++--- src/samplesrc/rod.pla | 83 ++++++++++++++++++++++-------------------- src/toolsrc/parse.c | 8 +++- 4 files changed, 54 insertions(+), 47 deletions(-) diff --git a/SANDBOX.PO b/SANDBOX.PO index 25b2a17fc461d0d8c0073b4a4591f6e2b79c494f..30f66ef9c74c1cec3f82c8dc5018d490937a244f 100755 GIT binary patch delta 471 zcmZp8z|ru4V?z*&sMoC?Of#ETO0*EoWoJCVrH^9d+*w;}n zI5IfI)t7+{)8DXh(`LrH?~Kb57@3x(Fmg2|EX!kL zW81QI+x8thfik}sCj}j3%$a;BNHwzk>V|7&SKF`7z51TP_iE(Tq^pZ=uD{uGbMnpG zH$L1Dy=i)r^``30$eXS=6K?LgdFH0ht=e1bZymekan=1llQ`kX9G<$XtWzUbB{y=+H-#P@er})~0Yu~SlUa!8s z7@Iwt9U@LLvMdtt`7oIysxffss>#7|`atqx WoXF(qaY8`WsyH<;|K_q1#ytSU6YX69 delta 387 zcmZp8z|ru4V?z*&s&0UfW3aEIUT|b^h^sFH!+$LXb_NG-hL;K=9Lfxj85nGoM0h5b zvuLU+JNvpYAOW_G3|tIG0&tZAAeEbsvRM00%V0dnm_Geb2BT_Z)77YJg;$%d&ba!X z!Q*Pk)!3^(HzRNA-L$>gdSlj&{WtF4SbyXE4d$EgZ*bjAyIFSg+D-Lak+%wNePDQV zmHAr1wT^4|t}$G{a{c-BitByXS6<(9{r`2j8%{S8r#oaa9$?ed*3s3|-^^I`i*Z{P z&{lM7w-ROTqMJW~)`s570a`12&Fb31Yx}RMUiZaj?RJM8#*>WG`SKVWw%^ZVJju+c zGJRzcqdt(jS;VNus4}e>L{3*PX1qDsfg`LbVNnPZ^M*~Ex1}-uWn2`-wJd>=ZCMH9 F9suY=ujv2) diff --git a/src/makefile b/src/makefile index acce732..c739677 100755 --- a/src/makefile +++ b/src/makefile @@ -140,7 +140,7 @@ $(MON): samplesrc/mon.pla $(PLVM02) $(PLASM) acme --setpc 4094 -o $(MON) samplesrc/mon.a $(ROD): samplesrc/rod.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMO < samplesrc/rod.pla > samplesrc/rod.a + ./$(PLASM) -AMOW < samplesrc/rod.pla > samplesrc/rod.a acme --setpc 4094 -o $(ROD) samplesrc/rod.a $(SIEVE): samplesrc/sieve.pla $(PLVM02) $(PLASM) @@ -220,19 +220,19 @@ $(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) acme --setpc 4094 -o $(DGRTEST) samplesrc/dgrtest.a $(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMO < samplesrc/rogue.pla > samplesrc/rogue.a + ./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a $(ROGUEIO): samplesrc/rogue.io.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMO < samplesrc/rogue.io.pla > samplesrc/rogue.io.a + ./$(PLASM) -AM < samplesrc/rogue.io.pla > samplesrc/rogue.io.a acme --setpc 4094 -o $(ROGUEIO) samplesrc/rogue.io.a $(ROGUECOMBAT): samplesrc/rogue.combat.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMO < samplesrc/rogue.combat.pla > samplesrc/rogue.combat.a + ./$(PLASM) -AM < samplesrc/rogue.combat.pla > samplesrc/rogue.combat.a acme --setpc 4094 -o $(ROGUECOMBAT) samplesrc/rogue.combat.a $(ROGUEMAP): samplesrc/rogue.map.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMO < samplesrc/rogue.map.pla > samplesrc/rogue.map.a + ./$(PLASM) -AM < samplesrc/rogue.map.pla > samplesrc/rogue.map.a acme --setpc 4094 -o $(ROGUEMAP) samplesrc/rogue.map.a $(HGR1): samplesrc/hgr1.pla samplesrc/hgr1test.pla $(PLVM02) $(PLASM) diff --git a/src/samplesrc/rod.pla b/src/samplesrc/rod.pla index a7d11e1..3582751 100644 --- a/src/samplesrc/rod.pla +++ b/src/samplesrc/rod.pla @@ -1,5 +1,5 @@ import cmdsys - predef syscall, call, memset, getc, putc, puts, modaddr + predef syscall(f,p)#1, call(adr,a,x,y,p)#1, memset(d,s,l)#1, getc#1, putc(c)#1, puts(s)#1, modaddr(a)#1 byte MACHID end // @@ -30,7 +30,7 @@ const page2 = 1 // // Predefined functions. // -predef a2keypressed, a2gotoxy, a2grmode, a2textmode +predef a2keypressed#1, a2gotoxy(x,y)#0, a2grmode(m)#0, a2textmode#0 // // String data. // @@ -71,7 +71,7 @@ end // // def grscrn(rowaddrs) // -asm grscrn +asm grscrn(rowaddrs)#0 GRSCRN = $26 GRSCRNL = GRSCRN GRSCRNH = GRSCRNL+1 @@ -79,12 +79,13 @@ GRSCRNH = GRSCRNL+1 STA GRSCRNL LDA ESTKH,X STA GRSCRNH + INX RTS end // // def grcolor(color) // -asm grcolor +asm grcolor(color)#0 GRCLR = $30 LDA #$0F AND ESTKL,X @@ -95,12 +96,13 @@ GRCLR = $30 ASL ORA GRCLR STA GRCLR + INX RTS end // // def grplot(x, y) // -asm grplot +asm grplot(x, y)#0 STY IPY LDA ESTKL,X AND #$FE @@ -125,56 +127,57 @@ asm grplot STA (DST),Y LDY IPY INX + INX RTS end // // Apple II routines. // -def a2keypressed +def a2keypressed#1 if ^keyboard >= 128 return ^keystrobe fin return FALSE end -def a2gotoxy(x, y) +def a2gotoxy(x, y)#0 ^$24 = x + ^$20 - return call($FB5B, y + ^$22, 0, 0, 0) + call($FB5B, y + ^$22, 0, 0, 0) end -def a2grmode(mix) +def a2grmode(mix)#0 call($FB2F, 0, 0, 0, 0) // initmode() call($FB40, 0, 0, 0, 0) // grmode() if !mix ^showfull fin call($FC58, 0, 0, 0, 0) // home() - return grscrn(@txt1scrn) // point to lo-res screen + grscrn(@txt1scrn) // point to lo-res screen end -def a2textmode +def a2textmode#0 call($FB39, 0, 0, 0, 0) // textmode() - return call($FC58, 0, 0, 0, 0) // home() + call($FC58, 0, 0, 0, 0) // home() end // // Apple III routines. // -def dev_control(devnum, code, list) +def dev_control(devnum, code, list)#1 byte params[5] - + params.0 = 3 params.1 = devnum params.2 = code params:3 = list return syscall($83, @params) end -def dev_status(devnum, code, list) +def dev_status(devnum, code, list)#1 byte params[5] - + params.0 = 3 params.1 = devnum params.2 = code params:3 = list return syscall($82, @params) end -def a3keypressed +def a3keypressed#1 byte count dev_status(devcons, 5, @count) if count @@ -182,13 +185,13 @@ def a3keypressed fin return FALSE end -def a3gotoxy(x, y) +def a3gotoxy(x, y)#0 putc(24) putc(x) putc(25) - return putc(y) + putc(y) end -def a3viewport(left, top, width, height) +def a3viewport(left, top, width, height)#0 putc(1) // Reset viewport putc(26) putc(left) @@ -198,9 +201,9 @@ def a3viewport(left, top, width, height) putc(left + width - 1) putc(top + height - 1) putc(3) - return a3gotoxy(0, 0) + a3gotoxy(0, 0) end -def a3grmode(mix) +def a3grmode(mix)#0 byte i if mix mix = 19 @@ -214,17 +217,17 @@ def a3grmode(mix) memset(txt1scrn[i], $0000, 40) // text screen memset(txt2scrn[i], $0000, 40) // color screen next - return grscrn(@txt2scrn) // point to color screen + grscrn(@txt2scrn) // point to color screen end -def a3textmode +def a3textmode#0 puts(@textbwmode) a3viewport(0, 0, 40, 24) - return putc(28) + putc(28) end // // Rod's Colors. // -def rod +def rod#0 byte i, j, k, w, fmi, fmk, color while TRUE for w = 3 to 50 @@ -234,16 +237,16 @@ def rod color = (j * 3) / (i + 3) + i * w / 12 fmi = 40 - i fmk = 40 - k - grcolor(color) - grplot(i, k) - grplot(k, i) - grplot(fmi, fmk) - grplot(fmk, fmi) - grplot(k, fmi) - grplot(fmi, k) - grplot(i, fmk) - grplot(fmk, i) - if keypressed() + grcolor(color)#0 + grplot(i, k)#0 + grplot(k, i)#0 + grplot(fmi, fmk)#0 + grplot(fmk, fmi)#0 + grplot(k, fmi)#0 + grplot(fmi, k)#0 + grplot(i, fmk)#0 + grplot(fmk, i)#0 + if keypressed()#1 return fin next @@ -271,10 +274,10 @@ when MACHID & $C8 fin otherwise // Apple ][ wend -grmode(MIXMODE) -gotoxy(11, 1) +grmode(MIXMODE)#0 +gotoxy(11, 1)#0 puts(@exitmsg) rod -textmode() +textmode()#0 puts(@goodbye) -done \ No newline at end of file +done diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index 943de13..645242f 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -1353,6 +1353,7 @@ int parse_vars(int type) parse_error("Invalid def return value count"); return (0); } + scan(); } type |= funcparms_type(cfnparms) | funcvals_type(cfnvals); idfunc_add(idstr, idlen, type, tag_new(type)); @@ -1362,6 +1363,7 @@ int parse_vars(int type) { idstr = tokenstr; idlen = tokenlen; + type &= ~FUNC_PARMVALS; cfnparms = 0; cfnvals = 1; // Default to one return value for compatibility if (scan() == OPEN_PAREN_TOKEN) @@ -1388,6 +1390,7 @@ int parse_vars(int type) parse_error("Invalid def return value count"); return (0); } + scan(); } type |= funcparms_type(cfnparms) | funcvals_type(cfnvals); idfunc_add(idstr, idlen, type, tag_new(type)); @@ -1597,6 +1600,7 @@ int parse_defs(void) parse_error("Invalid def return value count"); return (0); } + scan(); } type |= funcparms_type(cfnparms) | funcvals_type(infuncvals); if (idglobal_lookup(idstr, idlen) >= 0) @@ -1618,8 +1622,8 @@ int parse_defs(void) func_tag = tag_new(type); idfunc_add(idstr, idlen, type, func_tag); } - c = tokenstr[idlen]; - tokenstr[idlen] = '\0'; + c = idstr[idlen]; + idstr[idlen] = '\0'; emit_idfunc(func_tag, type, idstr, 0); idstr[idlen] = c; do