From 59095129e387b50c357e51dbc076795154376bb3 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sat, 6 May 2023 01:44:03 -0400 Subject: [PATCH] gr_viewer: get it like the others --- graphics/gr_viewer/Makefile | 16 +- graphics/gr_viewer/hardware.inc | 6 +- graphics/gr_viewer/hello.bas | 2 +- graphics/gr_viewer/lores_main.s | 100 +++++++ graphics/gr_viewer/make_gr_viewer.c | 246 +++++++++++++++ graphics/gr_viewer/plain/lady1.png | Bin 0 -> 12760 bytes graphics/gr_viewer/plain/plain.data | 2 + graphics/gr_viewer/{loader.s => rts.s} | 394 ++++--------------------- graphics/gr_viewer/zp.inc | 42 +++ graphics/gr_viewer/zx02_optim.s | 159 ++++++++++ 10 files changed, 630 insertions(+), 337 deletions(-) create mode 100644 graphics/gr_viewer/lores_main.s create mode 100644 graphics/gr_viewer/make_gr_viewer.c create mode 100644 graphics/gr_viewer/plain/lady1.png create mode 100644 graphics/gr_viewer/plain/plain.data rename graphics/gr_viewer/{loader.s => rts.s} (61%) create mode 100644 graphics/gr_viewer/zp.inc create mode 100644 graphics/gr_viewer/zx02_optim.s diff --git a/graphics/gr_viewer/Makefile b/graphics/gr_viewer/Makefile index e65a1ca1..9d160af0 100644 --- a/graphics/gr_viewer/Makefile +++ b/graphics/gr_viewer/Makefile @@ -4,7 +4,19 @@ DOS33 = ../../utils/dos33fs-utils/dos33 TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft PNG2DHGR = ../../utils/hgr-utils/png2dhgr -all: gr_viewer.dsk +all: make_gr_viewer + +### + +make_gr_viewer: make_gr_viewer.o + $(CC) $(LFLAGS) -o make_gr_viewer make_gr_viewer.o + +make_gr_viewer.o: make_gr_viewer.c + $(CC) $(CFLAGS) -c make_gr_viewer.c + +### + + gr_viewer.dsk: HELLO LOADER $(DOS33) -y gr_viewer.dsk SAVE A HELLO @@ -29,4 +41,4 @@ loader.o: loader.s clean: - rm -f *~ *.o LOADER HELLO *.lst + rm -f *~ *.o LOADER HELLO *.lst make_gr_viewer diff --git a/graphics/gr_viewer/hardware.inc b/graphics/gr_viewer/hardware.inc index 37327dbc..b4995e09 100644 --- a/graphics/gr_viewer/hardware.inc +++ b/graphics/gr_viewer/hardware.inc @@ -13,8 +13,8 @@ SET_GR = $C050 SET_TEXT = $C051 FULLGR = $C052 TEXTGR = $C053 -PAGE0 = $C054 -PAGE1 = $C055 +PAGE1 = $C054 +PAGE2 = $C055 LORES = $C056 ; Enable LORES graphics HIRES = $C057 ; Enable HIRES graphics AN3 = $C05E ; Annunciator 3 @@ -43,7 +43,7 @@ PTRIG = $C070 ;BELL = $FBDD ;; ring the bell ;BASCALC= $FBC1 ;; ;VTAB = $FC22 ;; VTAB to CV -;HOME = $FC58 ;; Clear the text screen +HOME = $FC58 ;; Clear the text screen WAIT = $FCA8 ;; delay 1/2(26+27A+5A^2) us ;SETINV = $FE80 ;; INVERSE ;SETNORM= $FE84 ;; NORMAL diff --git a/graphics/gr_viewer/hello.bas b/graphics/gr_viewer/hello.bas index 4d02d77e..859e0e29 100644 --- a/graphics/gr_viewer/hello.bas +++ b/graphics/gr_viewer/hello.bas @@ -1,4 +1,4 @@ 5 HOME 10 PRINT "SIMPLE LORES IMAGE VIEWER" - 20 PRINT CHR$(4)+"BRUN LOADER" + 20 PRINT CHR$(4)+"BRUN LORES" diff --git a/graphics/gr_viewer/lores_main.s b/graphics/gr_viewer/lores_main.s new file mode 100644 index 00000000..4c511d94 --- /dev/null +++ b/graphics/gr_viewer/lores_main.s @@ -0,0 +1,100 @@ +; VMW Productions GR/ZX02 viewer + +; by deater (Vince Weaver) + +.include "zp.inc" +.include "hardware.inc" + +WHICH = $E0 + +lores_start: + + ;=================== + ; Init RTS disk code + ;=================== + + jsr rts_init + + ;=================== + ; set graphics mode + ;=================== + jsr HOME + + bit LORES + bit FULLGR + bit SET_GR + bit PAGE1 + + lda #0 + sta WHICH + + ;=================== + ; Load graphics + ;=================== +load_loop: + + ;============================= + + ldx WHICH + + lda filenames_low,X + sta OUTL + lda filenames_high,X + sta OUTH + + jsr load_image + +wait_until_keypress: + lda KEYPRESS ; 4 + bpl wait_until_keypress ; 3 + bit KEYRESET ; clear the keyboard buffer + + cmp #$88 ; left button + bne inc_which + + dec WHICH + bpl which_ok + + ldx #(MAX_FILES-1) + bne store_which ; bra + +inc_which: + inc WHICH + ldx WHICH + cpx #MAX_FILES + bcc which_ok ; blt + + ldx #0 +store_which: + stx WHICH + +which_ok: + jmp load_loop + + ;========================== + ; Load Image + ;=========================== + +load_image: + bit PAGE1 + + jsr opendir_filename ; open and read entire file into memory + + lda #<$A000 + sta zx_src_l+1 + + lda #>$A000 + sta zx_src_h+1 + + lda #$08 + + jsr zx02_full_decomp + + bit PAGE2 + + rts + + + + .include "zx02_optim.s" + .include "rts.s" diff --git a/graphics/gr_viewer/make_gr_viewer.c b/graphics/gr_viewer/make_gr_viewer.c new file mode 100644 index 00000000..7269a7fe --- /dev/null +++ b/graphics/gr_viewer/make_gr_viewer.c @@ -0,0 +1,246 @@ +/* TODO: bail if will over-write files */ + + +#include +#include +#include +#include + +#define MAX_FILES 1024 + +static char *png_filenames[MAX_FILES]; +static char *zx02_filenames[MAX_FILES]; +static char *labels[MAX_FILES]; + +/* Format: + +file_label FILE.ZX02 file.png + +*/ + +int main(int argc, char **argv) { + + char *result; + char string[BUFSIZ]; + int num_files=0; + int i,j,count,line=0; + char temp_png[BUFSIZ]; + char temp_zx02[BUFSIZ]; + char temp_label[BUFSIZ]; + char s_filename[BUFSIZ]; + char filename_base[BUFSIZ]; + + FILE *sss; + + /******************************************/ + /* parse command line */ + /******************************************/ + + if (argc>1) { + strcpy(filename_base,argv[1]); + } + else { + strcpy(filename_base,"lores_plain"); + } + sprintf(s_filename,"%s.s",filename_base); + + /******************************************/ + /* scan in data */ + /******************************************/ + + while(1) { + line++; + result=fgets(string,BUFSIZ,stdin); + if (result==NULL) { + break; + } + if (result[0]=='#') continue; + + count=sscanf(string,"%s %s %s",temp_label,temp_zx02,temp_png); + if (count!=3) { + fprintf(stderr,"WARNING! weird input line %d (%d)\n",line,count); + fprintf(stderr,"\t%s",string); + } + else { + labels[num_files]=strdup(temp_label); + png_filenames[num_files]=strdup(temp_png); + zx02_filenames[num_files]=strdup(temp_zx02); + + num_files++; + if (num_files>=MAX_FILES) { + fprintf(stderr,"ERROR! Too many files!\n"); + exit(-1); + } + } + } + + if (num_files==0) { + fprintf(stderr,"ERROR! No files found!\n"); + exit(-1); + } + + /******************************************/ + /* generate S file */ + /******************************************/ + + sss=fopen(s_filename,"w"); + if (sss==NULL) { + fprintf(stderr,"ERRROR opening %s\n",s_filename); + exit(-1); + } + + + fprintf(sss,"; Some nice hires images\n\n"); + fprintf(sss,".include \"../lores_main.s\"\n\n"); + fprintf(sss,"MAX_FILES = %d\n\n",num_files); + + fprintf(sss,"filenames_low:\n"); + for(i=0;i%s_filename\n",labels[i]); + } + fprintf(sss,"\n"); + + fprintf(sss,"; filename to open is 30-character Apple text:\n"); + + for(i=0;i HELLO\n\n"); + + fprintf(sss,"####\n\n"); + + fprintf(sss,"%s.dsk:\tHELLO LORES\\\n",filename_base); + for(i=0;i-*Zrz)ovQo&J2N%&zHhJYXLUc_t83QOiqq0i#KEM%1ONay%1UxN@T(U513^cE ze>aHYd;$P~?*sIVymTymf$pAewhqovpqIZp6bSWmumu487V2^xvNoF2q8_YCI+3k# zInXwQJ0qS1hdk2DGBf_REvUc1S|*nY1g+yD3>-Y%e%-i_3Ayxxu^O`1WyFM3m63{Q z?)yJn+%8J)+;=^kZiDadcf23HUqSCEm6YHzx~6)#XnXJozbZQ8c-WB>kaSCY`PF_0 z7JTbdd@LcCq%=OaEq4GbCR-8wxs80+Sy#bV6Vesc@U{QW`}Xqw=$w6I-123_`-gnC zw=Fz#adi9NH+qlAdPPGkA4(GPnXm6TsVZNNef`$;SpwD<`O~$4Mt+Oe%q5r0?@k_shnL<7j+&k8#j0N~P0xW>?5KpYv;8CuepLN@>Hp+NbEBUM3K`75 z7_mF%4LS?^LG$wG=`!v6qmA=)y7GG2Z`_gO>p`PdIN%YbxF6Z)8=933pGcBwvjsJE zuqFG}kGvNJS_3X@rY;1FBdOdUOf2z(@bR{Su!IDcJ4XXG`B`@{! zdZ;9j`N!V&t>h(UzaShdz*^11e;aIhu>(T>00gL>Pt%REzhbVP%k-iqVY?d zJ|f-V%NL1MyTV%;FwS?j!{94IRkn8-Itf~hb4I$OP17cI%?n_YH_o4`bKcr^Mv+R- zFR9dwnmBdBCdYC_Umj9T+@jMz<2z+3!KHLLSH2nHJL7n(0ed^z^&uXs+ZZ|nt*Ps} zW6Jbd@PBUBa?pHBH=`l8v#F~g?z6BXS-iDOIcpw#e_eU~x-yEAmD(soE-88T#v7AM zXfU3f0Bexwq#8YCLYn*ONCk18OhvXhPDi3JWT@SPh-$P|3mCDZR#znD`(jQ zi|ZP@r$*7Oo7@1aQV$55cn*Y`)LWb+h?R?1Z6b$;JN7J$h zs%)PN2y|U~o0MXb+ZBDj-`~&gGn_X!t9z-00a#*3%(8>|uZ$+`GQP#?9xzU@6*i%B zr!K53@E^W~%&kT0OJB}94oUEKycPF-#Wl?;ei*5HbDss5b2J;&n?f4oJvlU&O=Co!_N^TrH_PUg!Y8{l_ zdun59m+G)xo!wdQYdjV_#7BI{8S^Bp=i8Gygg5BsNs4(~Vk}%Lcv{Be*edDMdxo9t zDLjL>syHQ`GQ6!s^K1_7!<@EE70up>l@KJP5We+0S{B2Y(KvJ{6IZ1Y^8o?usS%(u{zC-zJGp5%gGhK)5(XV`Mu8wqBDLWBfJhczd*TL_=ikF1x&v zQo5EwvtWCgdTettdspv@_tA{qh%b}L#ae`cC#6RBX$JQKCegYnwDQa86)~Av1dmu)4+9j1alRPqos13dfIC|e$C+%yiSh&H-EWjasWy7wn$T`{(%5ElkdYvX~m(A^3=!%4;VC*?!j~B;_EiCe; z)Qt^@KVm?0$8Y75fJ%h2=a{<_oG(hqx{YjpE z3`l2dFg@vIwT)E5XcJry+(Wtpwx>o`gT1pz; zw{(%CGVZ6`Qrh#~ywxEt`T%=0j$TTK)F*1hpGv9#GM%?-24w2vG)ge`l_< zMm=g-miY-b@77QBX(OTBG<&zUY*J?+Ts7>UG-+{<*r1PId?huc&Ae88%{&SHl+HU} zb}F)zhFtuiVT=SfuHV#6bDxl>kiM1;-$?qoPFU#YzV(zby>wTws2*t`we?Fq4nCl0 z%$8ys#779*>iAd&kpa<2-7{6b$rV4djZV?3pQB)3#D2z?ipZ?@siH13@iq+jEnZwU zt)km2Hag}9_r`qh-t@60vR`-hGjBsQd1V=`L#>*tX>#A8L?ZDWqJ&A$zCDA%xSwI& zr$ZQCQ04~K*6`Ru8AFzo4~6#1I(%;GW|$sg>N<>wDGYj5L^&PWWCrBSBg1atG4b+Z ztwZ=)A2X_nmsrBbnj=EV)XB^Vl5;1uD&i94wmuqD;22Y9KNoB& zxRw{F7n|}TleaxiQ0fuQStEml3owAS_yAubuc*kA1OWsaz!yr{+Oc-&Du4$mCpKTGJ4*799L22;$HkAw*Xj!pM|!nNA;shxsk_nRnx86ImqmGk@Y+V%<|E(2U2Sb;l6-eP zS+%nYRuHNMPb$&63Phn2+(Truou%o=_Gq}`4Bf1qL%?Uf zLMa?#S+EUx8mopa6Dw9V?OVK1?zYx?^ZN4PM`0FBT z=M_&u207{BU;U&$gq?Qxugc@235=t>#q2Lu3ol$qPwYNL-kbaAn-rLdXB_tE!d)MQ z5*^9dfKiYt9w7&9HM#(K${OdQO$A|Ibc^t5y{2ma;wWgJ+gIdr)HWZ(u*&8TS9)x8 z91xd#j7#~sun9XIEj}M3#j_zv=R7)9HuUxO$LE}x41&-_4@Wa?KD1f&j$HQ!ENvC( z4C2WFGGE4of%{o9;c;a$GS&V3()55z))4n#_s;`9S&sB}Slj3Rj{sBgPiZ-KW zq(U8^L%;HfP3dX58^c`$NnFdSLXte3uj}NNh(FT&XrIpbyq-DH&P)Fj@102D9|Yf0f;_{KVzMfff%CZq2gDZ z_vp>$LjGnIUdlueU$*j7j-e&DS|pY*z~jnTUQsly{s}Hz7)LJ)H&z4T<+DD?FePU^ z8LJHJf^^hx4C6sB3f@0GM^6nLX@ybI6XGAfW?EIO*_U%HwiJkzedgVuZNOfpfZQ`c zbb)EC^2|iYq1uD%y_DZm*d5w*F($IcqntU}OTi527y~d-Sb1^uKya~$ewPULgkn9# z2wW7OuA1Z>9v&>`Nd92_T9_Fli!Oz3f!Zy@pa--%m3=QTaUe8}S>p4?g?TPTrCccGFqL~3#6kcfgctWHrlqGqhwgx$d!QxT9)*ybF z&0g1fDhAQjz^QRrw^Z9mXsv$+C(Cv%M~`WBxbRqI&#Z+g()`?^!6W+T_PYPuRZKHbuyi(|3P#zakL>yXEPdV2-C!~wg}?TfJnMyl?yC~^-s2gr)(g!l>4 zppci3@U9YKvaKtZ&KzE$1|xtliZoqnn2|x*j|4r8pEC){EP3h|tlXpf*3%MZ>YX0h zKws0GNq$tTV4k)puBIrKZ^$+zG-d9?n4DrDNCetE?dqY3u|7 z&&gG^6FO>&ipkniH5CR|hf|d_pN=ZZ-HO(q8hg^3)q%B|D(Cx*2+MI;6Ad;1ry<6= zG6)HR#a~mun6cRIss_rN(>pvP5H0&qh*3EeLV8ABvGA^IvP&*`g0>!S2) z#ssT2J{4Aua(ZTUu31S@6XHJ3nb^gcWcqnXRBcgk#Q818=tw;N z5}oMMxnz<-s_*BkD?sr8MCW5NV@=l(&>bqZry@3?T#ZSu8*2iqp=}!)# zo@WMhB|0)k?+9eZNlSDsABJQlPlJ+JJP;aLgiw*sfnuw;Lvdc_pM%&t**sTJ1soZY za&07l#)Wh&h*>>d)Q7y&;up^N^cOeM&BAUiOfyYnFGac?@t`dez%QkfY*#(Z-O|RD zx^lQ5>d%TwZa&MsIQcN_-_a5JLRJZSTzQOEak!fVp)JIH261`26pmk3nH&|5M$!{a zPN08~<5JiY`-ua~$jB$uq%pVASt9m^Z#;CKomM47ZdqQqa*RFFm(%SqFp~>C-rsVh zo5q*##hLVOcy5MTYaOaBI@1qkk#R}>g5{72|NE+w{riZqGtDHstE>F&`sARtu@fKX zADx3dKiCZuN3dEC<(J$-Ysyn@P|2SrOE_0N-CbJc89=Cr*vELloKE|!J?u>u!~bNa z@@nFQuq~V}l#p@BZW#9rhUYM_{~RaxBfdOkoY>eS7m$6a1c9Vd2pFqJ@VnpZ_*9`h zhioLQ`g(mo5%h$t%TQy_mln?F8TEnIz=#{1QG5|Y zcxgkrXHj^B98rBpXW!hF`b35)MBx%fSY;x`@K<)nLL|@+fB4U}j?Y^mFmHhtHM;lpi`(q(nu-e_CfblM> zu5Pjku~dpkzr45(Ld1HleC&nNwQ@mr?q-+2Q2LG7_})oRA8j?B&*Mv94dGXZS~}C{ znI>BDCgoMrvV9wD_oX7;(rkDctWvOPD^k&{I91X_IciNdb;Il^WQj5?j3@4mCq_Gj z*ZxUweE5Lxv(-km$<(b-qK4#CvW&k>Qm<~c|5Pm%!e1LnTJnlQ_eJtgNgy@Heqsiu z&BNv_PmqkSg>nnIqh$NMXa&=m*P9aG*bN5vxLFuTV4yG(7ztS8khAi$_8wUB9%guA z;VZ)yFbH_ic3RnbCTY@8GOb@ieQSvk`BaXRnoAeQ3Vsla?%wgV3`i9>+sVlm$_OB$ zwdk;TaD1A5M#+L0WG|EL(&XE~v9UHHMJW*y){joMJ1IgzxVApiOuK1K82bFq%{kQ_ zZ86y`$7~N0W+LM2788(ZiskvKT71(+eX$^H9zF$wWI zIW`OjC*CDWSSEv|HtxzT#k5p3;y|5b%F116KwR`uC;kN5%h}xZlFWn1ESF5ZMmofl zHx7=1x*E7B-dd>0X_h_ukK0m~@)v}W)@54;aEfvJ5e`jm6(ePyFU%K9NE(A2y;RK{ zglEcZIXv{IX#=m21*efYd?oNcnVe=ijL@>N80$aMxuiPoe#KrW9~}CX#d#tgF?Inm zk@D8h*Pop8iD(oAcp)>eDqxM+ZI!D`YaAc!n-0PKWDN6V>~sunpR3 z&``tk&p}!-G?Tm@uOOr7LgkzJiiYGSBvK1!z}=(nctPaTd)0vMk^J5us+lIV*z}CKR#E#U zot*`yDjMA<1axxmAc25pKJVPXrAl16hAeARGEH*f*ZEG0p0WfO1j(o&+vHe>K2~cy z!30ui4OXwN@m*0cf(Qv|M#UOEBiX%74nEMO2o1=KDQor0V2N$BIu7XG`6F^q6R1>5 z4~$ecr-m&a5uUgp2(sJ`AVeOyEzKeDyL^@Yz!kP_G#c|cCl-Air-uZg(lJk*Q%ym& zjjkv(x;jcx2e(#?t38brM(WAT15=YI1_mbzSmzXg$^oXgxCG?k zo-zQRYIhgb?gKF7+16n=VReW7C7ho>?qqHLn4l-1YtKec%zDSXX8l1HU>HPESspVT zo0C9qCB|C~#(1aijyklrD=Ex<+wG`0q4^UF)Lhssl+_*a3QvyM17`m!5!7gvHf+I; zNK_Y&dgcd0SWL(=BypNM2kYY_jFk*2rxd%!8`v;~=iHd1C?Rp5O2wAiC{6eObhqb8 z4D@TPN^+#4Wb6U-+{;Rpi^%k%jNm>LuGa@$3%*q=l!m^3DBxNOuS8*`C2j%I zgmM65o#$6^d&hjI$xScvFXeq`7sE;A#dnI!lFuyh!-4Y878p&GabmV#$V)VI2FWI`_%VgG)Gs+Ux=bJZI1AG39-9 zI--j9vDBgYamddFW;#Z2 zWZ}2tUOd02eFH@7aaP!y?JsDzs5z^v^v}wiPw+xbe>UTE+gSA!ZI4tQ#HhFX6-6u> zS5?2cC*UZ3nw!(xVoUeaIg za+T3~NxzJv*FIQKe7?zUkmR@k^y?7eL$jhfdd1D}`PzR~7ueoR9#5`)Qo+saum+@c zc}$JyNXGzR`Jo_FXEyCL$Vt~oP(k*B+S2}wHx=LIq)J?e>D(A~ZVTz!5RB5vWGk!- z`q9ohw&HeC+(7YgRiCj`j3J}^VW7DzNpYH4?2`-nPwBSdx>LNi;nGj0fG=Q|(5dJG zOwEYR1xtXuJ(rzwXjiKWj*R{rw*~Z9cPjd~0k8eK?p%4g9sKvIw~Lyb>#jA~^zP)Y zd!8N;&gjfIlDH%LaJpv1*Q8uVcVRZY`C3v;59VAZLv%A~j5=`6kZ zC~HrdtQh4&^!Y+2iDoMGy`?=2#mk@OhbcRc6eb(?BJw=;0a4TaJVvYw9yZL+e+EIQ zW)YQ-kE%4U$)K5WO^es$$(zM2B<8TD5~jKv8ma3EpOn6jRaL0hmXSWujE&UG`gJQZ z5~}&;BxDvzeMJJ=KbjPuJfBA>1rT5ZK8@E|ec=8Ic<1whR>$0+k;P>u<^zNMqFopG z5d#IM+FfzzRCVaYgqNP`0w4)8JrvXCg&#`%p50_~>M}h3-XHff+Z?%HwOI@#D(ikW zpRmqUDJLaFUr_c*Me!)vBcnW#+}1Ac*USOFA}LG6`;)VR*_jwO9OHXVsIt_bPq%!M zj3l&?k-Rp;ldiVHbP~o}v8S$M3iO!i2N8JW4kF}|B5Uh%i*2k0Hb3JV8WTA(uFhh^YHPOL6Ns0{S!%8jb?JE`Z3kZ$O)ZfCOyZ;nQ}m_cX{Z( zkucQQ?YA9WzJ)a0J8$dp#T^WbhN{{5zZIId$0^D0NKm89Po*hmCeEc5hp>@FOGPI# zZ-rQ=Q1N6SC!v#jMRwuK@GFv3SVWGP#mW++I0JpaXc_nJt#q+($iTq5~N?|`F`#PF=(|A zCFQ}`cRnL9;fA>T&VKJRQuN(qL4n7`dp@hfGh{E`pgIKo6$V^smUQa57KQcphotF} z`{Exr%qw@P8cgQ2;IC^|J#oy$?JWppJ`XX~eMU|ZdmH-tXF8i^6tlkGZ-g06 zrx2II5z#Xu1MsDub-96x0N!17QRj!I2*fwbdPhWt$Pe06CL>RmPRIgc4Qiav5YhE1 znArwf+Q%YpItyd$L~jri6bIH%&PmEx##_V&+e>N&EbH{SJ6y?d@O912wPKn#wNwy7 zrn+6#mlh}U43|W{O*GBZgA_X)Wb3Bl^LCsFD<@tDo9oJ&nFr-Ov6!7$Twteaf+D&# z&LE$W+k9;WY?^M#$CD~K6lq_sHwNV z&{I2Zbyv)vWEOP6S6jHO)|W*G$Af+>@25*+wg|M<h`}U1!;#;0QudZppeN~Gokp1AL%Uq=jxN}*+NbaL~vOwyfxtvYy>@_`RvDC$a zUxc9Idmhp1bq$`e%OCX&Z%1v{OJ*!4jvo*P zi8Y6#)4j$30E7q!Sy?S*S=oObWq==G$O}ppSL&6b`eZ((BF~2FlLAUB5}E(RMdd^i zuSGYFStpWhDp{l~o3_5r(n?D8)2LRYRcLQ_l?^?d7Wj%&Bc4-d{UJ>zfei22?aATF z#vwJ3uSSg@$wO*}gFas^c7CavEHH|e02vbQkdt$h$56H^+;zCNv1gWO=l}8+cD{|p zgcJz!$lHmQ?~oRI>#&n|71vwKu^l%a*N@W%JfWW>dHz-CITfj&?U#Yl?YQ2LR#gd^ zoVHL|#sbi@E&Zg^sM=xwvB!Bcj`>YTgXUyx_Uyx^6~c)Oqz%XzAmV9lX%bSaM#s`@ zrK#W#y|f-b3EvTW>UR$`gi`1YJfr=I7wqdq%FMh}s)hL7zu_QR8`z4~NYQ*3OdV*hcObIw({M6lHS6CvbFWleu&2X9TK+q&Ko+>w3p>t9EeAD=jy^1$E4pM z!=5_94=^AMXc<;fuCC&fv1?zp^|wE5e|meR*8ZNhW5Dxckg)V;_=yug2l&YnBXuC4OM z=4r>pEi5d|1>xc1;Q_-nz%YMTFH1kLD~$dZ#2*-PP?)u+gS(f5n=9}arlpmex0g5w z1Rn?f%Rd))b@jjCU15K+0Oy0t&(fWXn-jw2;==WJ3z(O@4;&Fq4wnuT z=H~5b4VCwSx_Z(79m2-?FMD@yPv_s^*jRHxouMvpRTz9$?te_FsI0E_m&Gp%>>OO& ze_O%H{)eWQgYCb``iF17Mt+C$cSqpnf8qW^`(LsDR)%Y-tBc6FS$qF-PgzbJ^lN?* z8#ikQ8(rgL68-armvQh4`)bZQ<5%Lp~@kH`ofw&jS{;<>9gA;kFgF6tMjpgr=thyeci7 z|L)ZuDG01uC_r7hG3Y-MfB2j+wDLcx|cP=2tmuq~euH;*t6FTdq)C>v`L1vgI@ zOL#gRTrBONT<)%RzXyI1E+Va^EDqw~g#25gt*?i zO>O}pUS2*SVL=E)ScsQj@ZU-XP)``V5`STGLpXVPevkZ0iwHazII)($>J$#}TMmy! zMAj2(>E-6B=jP@t4*KO1@R#LZ!|L$mWMk=NDQD>gg@ZzPcts%mA`k&R2t}=xU-?I#@Tk0EP&OIJH6ynFmvuK$ud{12tT4YlDG=7T2;o_l_HJwPnMmi)rj zU><$}Zc7OKZ7U@7Pjr}@t(UK*Csf)F&Lf;FczOQj3dr(1QLO*e_O*xp$^x7)FoYlc z7h&9xKMCXdGhnV?J>y>yi*fy5oQVBa_*;{K+x;PfH!pZEj;|w)4OE`ZE{* zi!;EX|2xTl#P5IU`Y&Do5d;5`@_(!AzjXaa4E#sR|E;e7Z**b)dpiYnh5rijg>ROS zHHT*48!cWfH9dLwb%VyjLZkCR?ha65k(ZZ8JbpLP`(WXT^x!C#pP&CwI6-_NHnE)K z`7rVD@Br7(PmT_SUohO2j9~x(C;hJvf?t`W4_t`mrK~QGwvB>{EQGmWR*MJUd7CK9 zN$V-~f0|8-kAUDKTSO38ajxIKKY+SsAI@eKWMyMFHhl_)xc%v#4;#KhR~ zoY3jVGqsmfRDt7ViedwGD?s0FbDZ3VQ(Yu{{14;zzzBp;8+8vQ^gR*MkGQ5Fif9tj z@2Xd5#@U(Nh~P)hBGHO7QVaE&zV8v<-H-_&20^hc3Mw34BShC(f74M26}xD4f0lXo z=AC=fJCu*+;sctZ7o3K!*j5l^@hcO5?12ycL)gLXft-RU4M@V_9HU2KC!7YZxC=_y z#MhVwrUL5HW?f!HK>HSL$&9J~dRF@=@yg)`0x@rF$_VcGw^-TBgfilename - sta namhi - - ldy #29 -wipe_filename_loop: - lda #$A0 - sta (namlo),Y - dey - bpl wipe_filename_loop - - ldy #0 -copy_filename_loop: - lda (OUTL),Y - beq copy_filename_done - ora #$80 - sta (namlo),Y - iny - bne copy_filename_loop - -copy_filename_done: - jsr opendir ; open and read entire file into memory + ;====================== - ;============================== - ;============================== - -loop_forever: - - ; wait until keypressed - - bit KEYRESET - -wait_until_keypress: - lda KEYPRESS ; check if keypressed - bpl wait_until_keypress ; if not, loop - bit KEYRESET - - inc WHICH - lda WHICH - cmp #10 - bne no_new - lda #1 - sta WHICH - -no_new: - clc - adc #'0' - sta gr_filename+2 - - ; hope they updated the WHICH_LOAD value - - jmp which_load_loop - -; filename to open is 30-character Apple text, must be padded with space ($A0) +; filename to open is 30-character Apple text: filename: - .byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 - .byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 - .byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 - -filenames_low: - .byte gr_filename - -gr_filename: - .byte "F01.GR",0 + .byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 + .byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 + .byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 + .byte $A0,$A0,$A0,$A0,$A0,$A0 +;======================================================= +;======================================================= +;======================================================= ;unhook DOS and build nibble table - -init: +rts_init: ; patch to use current drive ; locate input paramater list @@ -230,6 +98,45 @@ L3: inx ; increment x x=4, a=0f rts + +;======================================================= +;======================================================= +;======================================================= + + ; filename in OUTL:OUTH + +opendir_filename: + + ; clear out the filename with $A0 (space) + + lda #filename + sta namhi + + ldy #29 +wipe_filename_loop: + lda #$A0 + sta (namlo),Y + dey + bpl wipe_filename_loop + + ldy #0 +copy_filename_loop: + lda (OUTL),Y + beq copy_filename_done + sta (namlo),Y + iny + bne copy_filename_loop + +copy_filename_done: + + ; fallthrough + +;======================================================= +;======================================================= +;======================================================= + ;=========================== ; opendir ;=========================== @@ -335,13 +242,18 @@ L5: ; increase load size by 4, to account for offst and length lda filbuf+2 + sta ldsizel ; store out raw size + adc #3 sta sizelo sta secsize lda filbuf+3 + sta ldsizeh ; store out raw size + adc #0 sta sizehi + sta ldsizeh beq readfirst lda #0 ; was **stz secsize** sta secsize @@ -420,7 +332,6 @@ L7: iny dex bpl L7 - rts @@ -614,184 +525,6 @@ L26: bne copy_cur -.if 0 - ;============================== - ; old code - - - ; [re-]read sector - -re_read_addr: - jsr readadr - -repeat_until_right_sector: - cmp reqsec - bne re_read_addr - - ;========================== - ; read sector data - ;========================== - ; - -readdata: -mlsmc07: - ldy $c0ec ; read data until valid - bpl readdata -find_D5: - cpy #$d5 ; if not D5, repeat - bne readdata -find_AA: -mlsmc08: - ldy $c0ec ; read data until valid, should be AA - bpl find_AA - cpy #$aa ; we need Y=#$AA later - bne find_D5 -find_AD: -mlsmc09:lda $c0ec ; read data until high bit set (valid) - bpl find_AD - eor #$ad ; should match $ad - bne * ; lock if didn't find $ad (failure) -L12: -mlsmc0A:ldx $c0ec ; read data until high bit set (valid) - bpl L12 - eor nibtbl-$80, x - sta bit2tbl-$aa, y - iny - bne L12 -L13: -mlsmc0B:ldx $c0ec ; read data until high bit set (valid) - bpl L13 - eor nibtbl-$80, x - sta (adrlo), y ; the real address - iny - cpy secsize - bne L13 - ldy #0 -L14: - ldx #$a9 -L15: - inx - beq L14 - lda (adrlo), y - lsr bit2tbl-$aa, x - rol - lsr bit2tbl-$aa, x - rol - sta (adrlo), y - iny - cpy secsize - bne L15 - rts - - ; no tricks here, just the regular stuff - - ;================= - ; readadr -- read address field - ;================= - ; Find address field, put track in cutrk, sector in tmpsec -readadr: -mlsmc0C:lda $c0ec ; read data until we find a $D5 - bpl readadr -adr_d5: - cmp #$d5 - bne readadr - -adr_aa: -mlsmc0D:lda $c0ec ; read data until we find a $AA - bpl adr_aa - cmp #$aa - bne adr_d5 - -adr_96: -mlsmc0E:lda $c0ec ; read data until we find a $96 - bpl adr_96 - cmp #$96 - bne adr_d5 - - ldy #3 ; three? - ; first read volume/volume - ; then track/track - ; then sector/sector? -adr_read_two_bytes: - sta curtrk ; store out current track - tax -L20: -mlsmc0F:lda $c0ec ; read until full value - bpl L20 - rol - sta tmpsec -L21: -mlsmc10:lda $c0ec ; read until full value - bpl L21 ; sector value is (v1<<1)&v2???? - and tmpsec - dey ; loop 3 times - bne adr_read_two_bytes - -seekret: - rts ; return - - ;================ - ; SEEK - ;================ - ; current track in curtrk - ; desired track in phase - -seek: - asl curtrk ; multiply by 2 - asl phase ; multiply by 2 - lda #0 - sta step -copy_cur: - lda curtrk ; load current track - sta tmptrk ; store as temptrk - sec ; calc current-desired - sbc phase - beq seekret ; if they match, we are done! - - bcs seek_neg ; if negative, skip ahead - eor #$ff ; ones-complement the distance - inc curtrk ; increment current (make it 2s comp?) - bcc L114 ; skip ahead -seek_neg: - adc #$fe - dec curtrk -L114: - cmp step - bcc L115 - lda step -L115: - cmp #8 - bcs L116 - tay - sec -L116: - lda curtrk - ldx step1, y - bne L118 -L117: - clc - lda tmptrk - ldx step2, y -L118: - stx tmpsec - and #3 - rol - tax -mlsmc11:sta $c0e0, x -L119: - ldx #$13 -L120: - dex - bne L120 - dec tmpsec - bne L119 - lsr - bcs L117 - inc step - bne copy_cur -.endif - - step1: .byte $01, $30, $28, $24, $20, $1e, $1d, $1c step2: .byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c @@ -799,7 +532,7 @@ sectbl: .byte $00,$0d,$0b,$09,$07,$05,$03,$01,$0e,$0c,$0a,$08,$06,$04,$02,$0f ; From $BA96 of DOS33 -;nibtbl: .res 128 ; = * +nibtbl: .res 128 ; = * ; .byte $00,$01,$98,$99,$02,$03,$9C,$04 ; $BA96 ; 00 ; .byte $05,$06,$A0,$A1,$A2,$A4,$A4,$A5 ; $BA9E ; 08 ; .byte $07,$08,$A8,$A9,$AA,$09,$0A,$0B ; $BAA6 ; 10 @@ -818,8 +551,7 @@ sectbl: .byte $00,$0d,$0b,$09,$07,$05,$03,$01,$0e,$0c,$0a,$08,$06,$04,$02,$0f ; .byte $00,$00,$00,$00,$00,$00,$00,$00 -;bit2tbl: .res 86 ; = nibtbl+128 -;filbuf: .res 4 ; = bit2tbl+86 +bit2tbl: .res 86 ; = nibtbl+128 +filbuf: .res 4 ; = bit2tbl+86 ;dataend = filbuf+4 - diff --git a/graphics/gr_viewer/zp.inc b/graphics/gr_viewer/zp.inc new file mode 100644 index 00000000..03664348 --- /dev/null +++ b/graphics/gr_viewer/zp.inc @@ -0,0 +1,42 @@ +;; ZX0 addresses + +ZX0_src = $00 +ZX0_dst = $02 +offset = $04 +bitr = $06 +pntr = $07 +WHICH_LOAD = $09 +CURRENT_DISK = $0A + + + + + adrlo = $26 ; constant from boot prom + adrhi = $27 ; constant from boot prom + tmpsec = $3c ; constant from boot prom + reqsec = $3d ; constant from boot prom + sizelo = $44 + sizehi = $45 + secsize = $46 + + INL = $EE + INH = $EF + + ldsizel = $f0 + ldsizeh = $f1 + + namlo = $fb + namhi = $fc + step = $fd ; state for stepper motor + tmptrk = $fe ; temporary copy of current track + phase = $ff ; current phase for /seek + + + + TEMPY = $fa + + OUTL = $fe ; for picking filename + OUTH = $ff + + + diff --git a/graphics/gr_viewer/zx02_optim.s b/graphics/gr_viewer/zx02_optim.s new file mode 100644 index 00000000..5eebc2e0 --- /dev/null +++ b/graphics/gr_viewer/zx02_optim.s @@ -0,0 +1,159 @@ +; De-compressor for ZX02 files +; ---------------------------- +; +; Decompress ZX02 data (6502 optimized format), optimized for speed and size +; 138 bytes code, 58.0 cycles/byte in test file. +; +; Compress with: +; zx02 input.bin output.zx0 +; +; (c) 2022 DMSC +; Code under MIT license, see LICENSE file. + + +;ZP=$80 + +;offset = ZP+0 +;ZX0_src = ZP+2 +;ZX0_dst = ZP+4 +;bitr = ZP+6 +;pntr = ZP+7 + + ; Initial values for offset, source, destination and bitr +;zx0_ini_block: +; .byte $00, $00, comp_data, out_addr, $80 + +;-------------------------------------------------- +; Decompress ZX0 data (6502 optimized format) + +zx02_full_decomp: +; ; Get initialization block +; ldy #7 +; +;copy_init: lda zx0_ini_block-1, y +; sta offset-1, y +; dey +; bne copy_init + + + sta ZX0_dst+1 ; page to output to in A +zx_src_l: + ldy #$dd + sty ZX0_src +zx_src_h: + ldy #$dd + sty ZX0_src+1 + ldy #$80 + sty bitr + ldy #0 + sty offset + sty offset+1 + sty ZX0_dst ; always on even page + +; Decode literal: Ccopy next N bytes from compressed file +; Elias(length) byte[1] byte[2] ... byte[N] +decode_literal: + jsr get_elias + +cop0: lda (ZX0_src), y + inc ZX0_src + bne plus1 + inc ZX0_src+1 +plus1: sta (ZX0_dst),y + inc ZX0_dst + bne plus2 + inc ZX0_dst+1 +plus2: dex + bne cop0 + + asl bitr + bcs dzx0s_new_offset + +; Copy from last offset (repeat N bytes from last offset) +; Elias(length) + jsr get_elias +dzx0s_copy: + lda ZX0_dst + sbc offset ; C=0 from get_elias + sta pntr + lda ZX0_dst+1 + sbc offset+1 + sta pntr+1 + +cop1: + lda (pntr), y + inc pntr + bne plus3 + inc pntr+1 +plus3: sta (ZX0_dst),y + inc ZX0_dst + bne plus4 + inc ZX0_dst+1 +plus4: dex + bne cop1 + + asl bitr + bcc decode_literal + +; Copy from new offset (repeat N bytes from new offset) +; Elias(MSB(offset)) LSB(offset) Elias(length-1) +dzx0s_new_offset: + ; Read elias code for high part of offset + jsr get_elias + beq exit ; Read a 0, signals the end + ; Decrease and divide by 2 + dex + txa + lsr ; @ + sta offset+1 + + ; Get low part of offset, a literal 7 bits + lda (ZX0_src), y + inc ZX0_src + bne plus5 + inc ZX0_src+1 +plus5: + ; Divide by 2 + ror ; @ + sta offset + + ; And get the copy length. + ; Start elias reading with the bit already in carry: + ldx #1 + jsr elias_skip1 + + inx + bcc dzx0s_copy + +; Read an elias-gamma interlaced code. +; ------------------------------------ +get_elias: + ; Initialize return value to #1 + ldx #1 + bne elias_start + +elias_get: ; Read next data bit to result + asl bitr + rol ; @ + tax + +elias_start: + ; Get one bit + asl bitr + bne elias_skip1 + + ; Read new bit from stream + lda (ZX0_src), y + inc ZX0_src + bne plus6 + inc ZX0_src+1 +plus6: ;sec ; not needed, C=1 guaranteed from last bit + rol ;@ + sta bitr + +elias_skip1: + txa + bcs elias_get + ; Got ending bit, stop reading +exit: + rts