From b50a0eb714c64dee65050539243e02ef2aa308b5 Mon Sep 17 00:00:00 2001
From: sparky4 <sparky4@4ch.maidlab.jp>
Date: Fri, 13 Jun 2014 12:06:51 -0500
Subject: [PATCH] 	modified:   16/DOS_GFX.EXE 	modified:  
 16/DOS_GFX.OBJ 	modified:   16/Project 16.bfproject 	modified:  
 16/dos_gfx.cpp 	modified:   16/dos_gfx.h 	new file:  
 16/lib/x/MODEX.BAK 	new file:   16/scrasm/80X86.ASC 	new file:  
 16/scrasm/80X86.TXT 	new file:   16/scrasm/CONSTANT.INC 	new file:  
 16/scrasm/DIAGONAL.MAP 	new file:   16/scrasm/DIAGONAL.PAL 	new
 file:   16/scrasm/DIAGONAL.TIL 	new file:   16/scrasm/GENMAP.C 	new
 file:   16/scrasm/GENMAP.EXE 	new file:   16/scrasm/GENMAP.LNK 	new
 file:   16/scrasm/GENMAP.OBJ 	new file:   16/scrasm/GENPAL.C 	new file:  
 16/scrasm/GENPAL.EXE 	new file:   16/scrasm/GENPAL.LNK 	new file:  
 16/scrasm/GENPAL.OBJ 	new file:   16/scrasm/GENSQ.C 	new file:  
 16/scrasm/GENSQ.EXE 	new file:   16/scrasm/GENSQ.LNK 	new file:  
 16/scrasm/GENSQ.OBJ 	new file:   16/scrasm/INIT.INC 	new file:  
 16/scrasm/KEYB.INC 	new file:   16/scrasm/LZTIMER.ASM 	new file:  
 16/scrasm/LZTIMER.OBJ 	new file:   16/scrasm/MAIN.ASM 	new file:  
 16/scrasm/MAIN.OBJ 	new file:   16/scrasm/MAKEFILE 	new file:  
 16/scrasm/MAP.INC 	new file:   16/scrasm/MODEX.INC 	new file:  
 16/scrasm/PAGE.INC 	new file:   16/scrasm/PALETTE.INC 	new file:  
 16/scrasm/SCROLL.DOC 	new file:   16/scrasm/SCROLL.EXE 	new file:  
 16/scrasm/SCROLL.INC 	new file:   16/scrasm/SCROLL.LNK new file:  
 16/scrasm/SCROLL.MAP 	new file:   16/scrasm/SCROLL.PAL 	new file:  
 16/scrasm/SCROLL.TIL 	new file:   16/scrasm/SPRITE.INC

---
 16/DOS_GFX.EXE          | Bin 35702 -> 35970 bytes
 16/DOS_GFX.OBJ          | Bin 5389 -> 5583 bytes
 16/Project 16.bfproject |  24 +-
 16/dos_gfx.cpp          |  55 ++--
 16/dos_gfx.h            |   8 +-
 16/lib/x/MODEX.BAK      | Bin 0 -> 25600 bytes
 16/scrasm/80X86.ASC     | 164 +++++++++++
 16/scrasm/80X86.TXT     | 494 +++++++++++++++++++++++++++++++
 16/scrasm/CONSTANT.INC  | 127 ++++++++
 16/scrasm/DIAGONAL.MAP  | Bin 0 -> 65057 bytes
 16/scrasm/DIAGONAL.PAL  | Bin 0 -> 768 bytes
 16/scrasm/DIAGONAL.TIL  | Bin 0 -> 65536 bytes
 16/scrasm/GENMAP.C      |  99 +++++++
 16/scrasm/GENMAP.EXE    | Bin 0 -> 18664 bytes
 16/scrasm/GENMAP.LNK    |   1 +
 16/scrasm/GENMAP.OBJ    | Bin 0 -> 2543 bytes
 16/scrasm/GENPAL.C      |  51 ++++
 16/scrasm/GENPAL.EXE    | Bin 0 -> 17676 bytes
 16/scrasm/GENPAL.LNK    |   1 +
 16/scrasm/GENPAL.OBJ    | Bin 0 -> 1895 bytes
 16/scrasm/GENSQ.C       | 102 +++++++
 16/scrasm/GENSQ.EXE     | Bin 0 -> 18916 bytes
 16/scrasm/GENSQ.LNK     |   1 +
 16/scrasm/GENSQ.OBJ     | Bin 0 -> 2977 bytes
 16/scrasm/INIT.INC      | 375 +++++++++++++++++++++++
 16/scrasm/KEYB.INC      | 237 +++++++++++++++
 16/scrasm/LZTIMER.ASM   | 636 ++++++++++++++++++++++++++++++++++++++++
 16/scrasm/LZTIMER.OBJ   | Bin 0 -> 3231 bytes
 16/scrasm/MAIN.ASM      | 134 +++++++++
 16/scrasm/MAIN.OBJ      | Bin 0 -> 18324 bytes
 16/scrasm/MAKEFILE      |  47 +++
 16/scrasm/MAP.INC       | 413 ++++++++++++++++++++++++++
 16/scrasm/MODEX.INC     |  88 ++++++
 16/scrasm/PAGE.INC      | 109 +++++++
 16/scrasm/PALETTE.INC   | 239 +++++++++++++++
 16/scrasm/SCROLL.DOC    | 297 +++++++++++++++++++
 16/scrasm/SCROLL.EXE    | Bin 0 -> 33596 bytes
 16/scrasm/SCROLL.INC    | 441 ++++++++++++++++++++++++++++
 16/scrasm/SCROLL.LNK    |   2 +
 16/scrasm/SCROLL.MAP    | Bin 0 -> 344 bytes
 16/scrasm/SCROLL.PAL    | Bin 0 -> 768 bytes
 16/scrasm/SCROLL.TIL    | Bin 0 -> 9984 bytes
 16/scrasm/SPRITE.INC    | 280 ++++++++++++++++++
 43 files changed, 4385 insertions(+), 40 deletions(-)
 create mode 100644 16/lib/x/MODEX.BAK
 create mode 100644 16/scrasm/80X86.ASC
 create mode 100644 16/scrasm/80X86.TXT
 create mode 100644 16/scrasm/CONSTANT.INC
 create mode 100644 16/scrasm/DIAGONAL.MAP
 create mode 100644 16/scrasm/DIAGONAL.PAL
 create mode 100644 16/scrasm/DIAGONAL.TIL
 create mode 100644 16/scrasm/GENMAP.C
 create mode 100644 16/scrasm/GENMAP.EXE
 create mode 100644 16/scrasm/GENMAP.LNK
 create mode 100644 16/scrasm/GENMAP.OBJ
 create mode 100644 16/scrasm/GENPAL.C
 create mode 100644 16/scrasm/GENPAL.EXE
 create mode 100644 16/scrasm/GENPAL.LNK
 create mode 100644 16/scrasm/GENPAL.OBJ
 create mode 100644 16/scrasm/GENSQ.C
 create mode 100644 16/scrasm/GENSQ.EXE
 create mode 100644 16/scrasm/GENSQ.LNK
 create mode 100644 16/scrasm/GENSQ.OBJ
 create mode 100644 16/scrasm/INIT.INC
 create mode 100644 16/scrasm/KEYB.INC
 create mode 100644 16/scrasm/LZTIMER.ASM
 create mode 100644 16/scrasm/LZTIMER.OBJ
 create mode 100644 16/scrasm/MAIN.ASM
 create mode 100644 16/scrasm/MAIN.OBJ
 create mode 100644 16/scrasm/MAKEFILE
 create mode 100644 16/scrasm/MAP.INC
 create mode 100644 16/scrasm/MODEX.INC
 create mode 100644 16/scrasm/PAGE.INC
 create mode 100644 16/scrasm/PALETTE.INC
 create mode 100644 16/scrasm/SCROLL.DOC
 create mode 100644 16/scrasm/SCROLL.EXE
 create mode 100644 16/scrasm/SCROLL.INC
 create mode 100644 16/scrasm/SCROLL.LNK
 create mode 100644 16/scrasm/SCROLL.MAP
 create mode 100644 16/scrasm/SCROLL.PAL
 create mode 100644 16/scrasm/SCROLL.TIL
 create mode 100644 16/scrasm/SPRITE.INC

diff --git a/16/DOS_GFX.EXE b/16/DOS_GFX.EXE
index 13b89317f3689d21e6f85000608aff996db46f4b..d4df1da3e32f74f72ff89c6c72677496f5b37b9e 100644
GIT binary patch
delta 15833
zcmZu&3tW^%*PmyXU6$L5irfWMR4xiA$W;&!R!~6XCf-<)i=f<u1@A7Vrt2b+kG^I0
zy-D<$Z(3Sfk@^;?rKJ_T`72W2qQb%?HS>Z>@cqv`3+nG{^}lE4%$YN1X3or<XP)KW
zKV;ABk?E7?FA;p%R_4k6!TS3X6imffy%l2~O!{03VeAfI9m<$JFd3Kyh`{?w#=ZhN
zfd_!voUt*$XTXoZ17HaBxdVq}3dK7>3ewwv=YS>^)3Y`tegs^?81qNN@ql9jW9vZO
ztr>e07-PfO8sMM6$3QpGmcm#w6n+S_0)MC(OC7@43R}jU>=>H@tO9lb-vB=WeL$lF
zV=s(kZ1*VW9j#~Vh$myw;~2{T76BE&Y9IkhlYqlWn~i5|ED!*!19k!*0DfMKg#c$D
z_a|t$H)D0cmp}*53yk%_DEKl~4lIP+V!(0&W3Ce!+pNde=U|iupkbg6cop~=xB+M;
zF;)re1-=G;25tj(lhGJ3A1DXvfOmoFKo}l`&H#D9HsCqnUEoV#>=eiYCxPpL-aMGG
zP+$@88VorD`Ze$?Aj7<?0Usa>C<hEcBk&gR5kQ}2Gp3H}id3n)^s0tQEx}FgGUTgN
zl)NN6pV}Ni<s((u>2uOD4OcgHyKZTz_EdL;g*Aw4WiI+ai|cuj0;|sXRP*PM9XXx$
z>2+;8a&9-<GIf`OMZ<PYXFz9g(|=^@uDziR&2p9sZB60LwL)rhgDh3uHDPK)v%tCU
zPo30~n)<lJFS4Q8gQY?yKdQmdz3AGTW~t4VWX)>xY{?ecHqlCMGqeG`Rux3%pKn&7
z-8rJSJVG|YTr89a2|tK?<$*HSD6v)UCwwgS%e@7Zn<WoRR5t86A!qj=1sm)y!oD!2
zxXo<pkZI-(*S?W$>Qh!vfZE^1ugwgyT0zWFxC#N{T7{Qotx#<dyfNyMEI@oy5$1@j
zy1BnUxap!Sxak|&M*=ey_9>i6cDN}!TKTSRtx%(s#@NLCRT-#n4d2u!tM))+d*yph
z)C%_>r6K(s(gBplps2eJg*R;KvxQLCN;#~Sgu0efdQd2;>sivIv)t5Yrc;pkNa&dX
zJ&!vX)fFP&!+ZRVEVy6!GP`ar?lB*x=ac-I40D_{m(Q}@S<P)T_K^oO^kI4onmY!~
zJ$2W{hw836MFTv*!l=2e?uzQYe&ej>A!GeD4`FBX5I&K&!;o#h$p-R2h4pJ5Zrt#&
zR#^A#Sxqlv5bdw&HA$ZdYo4YTo?sk<c<;syy#ZXjhm`j`R{jqt?`igj`$&yF3+bMX
z8+s(=eYYg#eWuc)ux74%AfFBCzKt9DNVmGH-K+r)mD+5k=XS@$&fT%O1)c3qZH`6*
z0W6i;T}*B|b9%$v{+jM5_~ghB;&#Lf2F(pv-`#uz?r9E1U3+62`fG0N*nAGEZl!WQ
zRH?f*nfR?}l7!=VtEI91HF`+5o49EtI?p89VPa~z=yZrevdhFQAxZz(h8^)L7;uX(
zmSziXw7N?h7YqY?<fa}B7*3r4e_gD)>x!HtTI85beK4QSs)uv4z}gog-*87>gZaJ}
z*RZL7nqIM~Usx}{pL1tp-zx%geZu-r@8{gR{;|62MR`Ny3Z_#<x-gymTIXMrTF`V4
zEp5J#shhjW%<b}qO=nci0T@<V`o#a3_?4W$xcL_PL}N|`SEyh<FHm=Fj%$#(@F#Uw
z9C4Lg%1S^!i1KEWT4;L+{Y%=>=)2DTRdznCqsrC0!!5O0p%9}j9feA9o~8Rph2k{a
z96a>fruj7nf;BmR-h%Tax7%{UFkWOK70IxrC=^G(woH;?gB3^F*bxb_nL?z@rjf`{
zHI5r=ae+FPa<8a$L`Dqp(En-E)WYi2r&!Y&kWX3DIgroUq~Ec`ns3`QT|o9r*4&RR
zD^f<2(I%uGS19T)_3ntmNq*`BTh=THe;&@(1sF~@cUskbe)2W5^whNDD7<vs$+}sH
z{9=^hwEKL+H@%0Zvg${MKfK!#k41kmDx1`Z$A);pl%wAdF&Bh<@fX|qPT;m1-E8GX
z^)Pv(o&2maPR3~Gu{=6&s7fHa^M?5g4~~k%YUGr&vUesj-af`bp)e#XQQQ6}S!1WH
zKBvzRFQXCD+t2V(DAZjeA2eLwc~;Y>P+T`Y-bc*dmK#og{j+d-(r0Zy(@5U3Z={ht
zDmvX!kZObb0e!IhHBaNHS)+`ju6aKF@1rr4e`}B*J^JZ#%H17Z>bY<9K>dABNc4_=
zTwmfxk2dXZ&c+&*LDOr<>Z|`wJmR5~#kd_EH%iMVdFz-uvT%f_kz4xexOyRi2JU!2
z>vz-0_|evUtpUBMZ|4jtF;iw}zo!1x(2{02^<<g2+$)HB+US)|<erzi4ONIxr^!}Y
z(g=?Bp6N&&qoyZ9nJud+GODv=TRzj3QQ>Cqu~h4zca;@pp#A#M>*I*+?Q@*iSAF7%
zOz=%5vcWex077>4?Tx?4jP_l!`tJ<pkT%Sf)wdhmevui}T{0{cZ4SJh=I8_}-S8bx
zbsZ*j5fLWl5Xqgm2jpn)L|g6@YX3sY*7*M_3sESbvHtR;exqB8Y|CYxP1yI97Eu3#
zQEPVnCY7}t*2xSD&9?OGVhz=1TP|0}kj1+uPviYItdw1UH=Q^gle4I;&_Ev|`GMSy
z9f854pyQH3(`RbHitF5@H)GWaXirO3I|DtajxxxT$b=v_xF-!@pTW#<%kXE{Uw;|S
z8a^e-+#nYc*$~9FzaB&(r?_-V8}<R6*QCqpuI7i*Oh#bPb;Ikwn{@dDNMr_&u}~<^
zH+z_2C5an@JzW%vjb~lu-X9+kVrJBzn)~M)TJ5~kbJFHgc}s96sdWgUxKqpxnMLHS
zkcmY88^V{+gAjkp`Gk%kGCQ;&i7am1FEiNh$0n1;*S%c%7WM)en@_W2@}da)W>%SC
z`1)<LO{a%^eI3IoKf!GInAAocL)2&sdv}KMMqI;uU}ya$WAJFRE%$U$VV|y48SRAI
zVW(EkCp&Y)97B2eN-DN~qS%YKZwyYAZMj$NVai~B@9AC)`?SWID!(1(M5gD4*)MRE
z1h|&Bpydszk(yV*H~fin<DN982G|h+omCdbILinn9NsQx{(|#TZON`LuC4EHN|Rmx
zmAXt578$OgX10WXs&WZ4YI>WT!o>85_w+A?eIB+G&l!R8p9LncXyF!nDeRJom8WEu
zU^NINwS7QJ237}HmrSgsF3gS<3Fp`wCSC2aUoG&^R0Lgbm~^$vAms&CgFsTGi%aQk
z!Rr7|Qr0eOqH`u%I1DR}o2+<>C0X%0Nl6tYsdm{@ER%kL$ykGsE&C14JtsR5ZW}%(
z{6u(gcw+dM;S0md!+#7P|4jJq@H^p%puey^t9%A>XO-LVeLB<Fy{VhIWhv+S)w{Wb
ziGGpJGI@kJGjhV*&0%jgJqy%^wRN?1HEl!knK0w`$1lo_A=9U0ZdGq?Y0>?8^LkHz
zaBWzBh`Q^paQuwCSvKTmz0xTxu>S*A8`$#aK~y+0^hRvAb?uG7md0A~i%7>2n422q
zraqgMOQ0twrR^8vF|_(Ha;(kcR?(a|A<8ShHcV@t<8HjV=yMqxF!z%hOTWg=VFt5L
zYLtGB&mtj7sGgRn9guiN+!HlchW@ogdDyp1HFc=13qioXAq_^2vgwp~FUsArWhyiq
z%={WpiSE;a%3Q)4QzMOTX^}>CMx@a`E3$TjQqT=)OaOBxm`Px!L^ef78r)(d4eGc^
zgS{qlyGHq}GCOi|r^#l&eUv$GGMx`|U`ta%WD_)KR0&N`qERL^r9_G!Pjm7lueEMM
zs~XEDw5w6cHP#7DXkDX}Yb+C*vLg3oi+$5Z>Qf`nY#27qpzv!<LrTq48IgXz%GAi{
zGaD><K8x~clvh%o8=^I*p|oXz_xy}ev5^sH*W3B__<p-#rtz%t;r$<tw~XKVHO5Aw
zP=i8!;0)h~zCG(@@^8V3j*R$Wy^Zf9->)_-bdlfpGrC2SU>w+bs~O-wfZ$g>ryrai
z&~3?eM?I-=(*M(F#WgxTRwv$z_Ryope)q?13o~Y^+J0;MO@0cKwb_OOoqC(&m*m~Y
zTjWOqZ*147Jmsw&a4qVV87-JW9{{gL<rfhg9l0(XBrZ}PXv|UiMPRbld4p&o^`noN
zZ7)>ScFK=`DZh!iaSAh@=B>7gnKABTQFE$Pa|))yFG7i$z96XS$)!p5=$@GID!pyA
z3Y&p#G{ZOj>xUt#$Hwq^$J8QVjK<vJp|?^N*wWU~)?sWnZnaHlvQMZ}J0@)3IxJyw
zXOnY6lV`&A7ltQHzGtv^O}PJ4lN)j1H{%knhv9+In4{YC$abZlF-y7Wp~uQ`2EChe
z0*M+=E6f@BcUu>)MSf(TKtAP&>f9v<7m3LxRg(t<lue@t1k7jzH+IWpd|&t^*ggS1
zJ-HKobxV-ns%x!p+3_Lk^E29eB=|MDCK#UW`^(SFsCG^ePtEkVc24l?4|b)m(Fx*T
zGyUgyCI}j9zs7MOmi_g8e^p-!Y#CUtPb~`!F*-@6j7#8_azpt3<k#q#U|O2v62$eh
z{4Gw*3_pd#Z1_y^-C1L8oWknc>syQ(HBE^4>#R}2Hqjz!48A8OdEq-NDR|UVGT4A@
z+itYokl!-Y+%vhF_-4{f$o3@Z1WU0r*&!Y^TI$<-@sMhqbym|;I}3tS<ttsMGM!^<
z2mRaLafG`LL|!J5owK$V_E~o79Iz7}k=?`?Z4*CBp6I+SY-aT>t$c&^_QGBi+dolk
zo8n<b{(L~CdvqSxYs*unh_$H!*1bt~$y1WEl2;~gOBN5M92x!ZTUGLFA2LIhN~p1=
zeufzzwcTvHDep0CxaUWEuDD?~PB!tQ*@@Ks)TvRAMK=8`_uIa8TT0u{e!kDurmP=g
z{BHVmztLM8QYLo>es*1L{Ekb!UYF8#t?k-rT<zc(J(~KuwWhkH#3Q!4u&|)gL!3Xy
z1=w!^zm`6tkmi2WJ#D<qDIAw&geO0RxcDj*wHfig3I&ecXetvtqOmLlt5)3N2_80f
z_zqoz`zyg?H*UlPk7Y-{$}kt~cj2mwJ_4JbB}hpYtP;C3$2n2`II!eZy5&!bY!-d9
zT!apBMwYw&56GNFp?PtcZdCwXb3Im7i-Rv(j@6l*ou2HMTUAPh_zX1FGL^Af<WZiL
z{x{{(k+|Z6O(>t9_BZ7o(^v$HmK3C>{EYw}vzY_R%?nElN~;QVNDel>c-qdnZo*fh
z`&<{9pOrXuuCqSQiZN%1D3%uJ@`_0Ku{iBFtxyMBW@r3OQyqzn?UQVcjs2VQ+F4u~
z)z|!Oc@hg}wvd6q+`sE=4vfQXB~w;ZVyFv|dTd;SI3(L$s2BaSeT7zWLAHx<M_ifh
z>+FaNTSv&ri-Y*s4-9;OT0EJJ{-W3e#pYE7ODhX<^N}1Jo_$GD8O%wG`J4W<pnSmG
zxW6fHeOy2N@9N)5Vm^qacz;t9|3*PA+!p_7JQ9*b{XBO(8^1EoMV2^3JUP!z(21A9
zDia^g^9?VDA!Df@1!cN|%KRly_G1^yR>KFC`Q;e4N-7%cqm7-oc)pwPi>ROP0)>0$
zyM)Kt<02R$=Edc?B_-u~Pm2G5GA|67Sw*F3{2!|_A1mIPA0-PPCk8C=6Sj!j1ujCC
zxORa{c)l0r0R2=J=9QFJ6_CO~1J-%tnizRyVP!!<VZ~Erp*~{k0yp7#@g`KA6s;Dz
z%)5$f?u`&KE7q0ga^c6SXa^V$o~o?8pm1qnDfe~c2c~>A%4fg~MM=qE<$<ymQNPed
z_(|Nm&|jz(&o6WrUKX$8`;ut2$YorJA8J99qOfXp86S|xTBo9nLIG9T&K!HEXynGr
z;BHuLU=FsuR9w5rU05UT#kXEOvB*VOA%45aU8V{WdltEcSq0&7ff~@}m6!%-uxb>_
zG*nhdLqtj+tKBTl&T$cTipz8Sg}21LIWA%6aoxTQ5}53&N@=+dYMO$r32T%oi_1&P
z^PirF4dP8`Y7wopF5zvETLU?>swI`nLFqFvP_u9w{|I?S+5fjj6Dls&x(TO5z1H16
z7`q|{n**C1|L{%KSuU_+Vw*Nm|8Fo)1DAm=;CJ9YKy~Z@Ctwud1xyCQffOJe$N|cL
zm4E@*3+w~_1-u2|E|}r*i**Bk0V6Oe-oPXv7>JVLt<VA_mI6AU7T5*s0p0~Z0losh
z1%3i<1NQ-jmE;PH0s??(Knjot6ai}h5jY5(0{#m;0QvwK9K{kC0u04nE*p-7Bj5py
z1-t+sz#o_lL;|tEOdthF1Lgu+ARj0KmI0MO4Nwbg0d@d8ffs<6frG$t;3MD@-~#X^
z?kQL+@C#rC_YMFS0=d94pbXFfTY);@IpBHV1>hy%pTO(DTfh<EUEmCG5%?bX8MqC|
zlz6cR3<W%Z03aODPs3LVkOLF}rNA2C1>g{H8n_JH0uX63XTTqr0VDzWKrv7WtOja<
zO~A8&5qJ?e0K5sj0~`lhfOg=PIkRFa_^2D;rxI(IcrFOR`4h{g<G`Q660lNcvRN#d
zrLs9Jon^30HlHnE3z?SXvOJd03Rod4VkK+^t7bK9C0oT-v-NBP+^QB^)H7@o-gj<e
z2DY6US)JIw#7X}Wdzt+Y`zL#aHL_P(6MLN<VE<xou!HOndy~Dzj<C1cJM1WXm%Yc{
zXCJT=>?8Iu`-GiiU$XzOcJ?FtiT%ocW7k<XyT$IX9`=Ae#A@uL2LQoF7%tceBLsWF
zL2wkj1s}mz@Dl=rNy20yP?#bF>xB>@R0tO$gsDQLFinUSVua~Jyr2<g2#LZ>VV002
zBnv6RY#~*cBcux%!UAETkRxb?B|^SXAQTD3!ZM*mC>6?ta-l+4Ayf%+EC+;J{L_yQ
zB|1{DNI36?*#K`T^4=0tp%`EWSYtUbYi4Z+kHnmGW1gK+^|a`p@8aYokPe%<)AGto
z$}87+7J7MC*`u^u%*)>t9Iv8Mg;txMF-r}uQOZ~5mgQ@QAzu|n<;vvjjQF%<q)0EG
z$z2PaNBqG>DOw8+UZs_ac8aqKTxLGQD-B7`)}~KSi;qu9h)<l6kii%!^p7Bg7Kr2G
zGm>Y=#gi!&Q;BDloIN8xBPKmHemZ2`sG&&lNP(Md6kg>OAjZH07_X_Fo|KrHJ(;w{
zKE<0iiL{-IB00<S%vh3(ot=#w$<7;)Maxt|-SwD8vWn#F)R+{i`yS6*BA=O&nwTAr
z(1X|g%0j?4gVUg(BzHCX%9(LiR9VSGJmQgpJ&DA#;oZxK&(28Ch)<<4JCQ(q^&o%x
z?4;Rg;E-X9cpVJM?92?RL%jc;Me^Wj5|fh9hhfZCF68hA&84tSE814OmHvzNQD&~y
zVj9ZIC4Kc=Or_1M(&bj_w7iW~Hlz=71*?j|;=JDmco_D$bZG+baNf}AIM<SalH}s5
z(p-eF)Q3Cbb2^9NWZhf5Rh3qoS6zv-O<bfKsXjSiNnTNLNxnEi=O#X^auvU?a&@4A
zxyXyHwA!SK)TN~<xupe6e7kBy6sdc6KwUz5QE{P;(aboi$zV8UW>7N8#PPh!6klrj
zV7DZRsa5vlcPEpmG--*+F*D+kqbluOtx}7@DPMxq#Hngj_6A9fR$EA+m!#(K5ME!a
zO)M+crRmD5P@hb;v^DWH#bw1$@XH4HakJB5kCx_Me5uk)e74d~PZe$G)MeI^LQQc=
zL6w#-oMj`3KLm~A0S!hCOa|47vo|$n3Ks{Q%zP~IG1P@6)m25(WZKDT(!tYeV=9;C
z@wE~@j^u`UX|-isd6{l<;DCNU8YNsnIlvP?STT0U1(``vJeGTQqWJuZ5%y$E3g=_8
zv}HvFxfM$amWrt>eDpM^S>vf4^HLtu!blR&;^H<CFC_7_@|uE5;^%vr`jlVJBi4aF
zP4ebCq%amt(z}lHETDo1uv)4g>O*oEM?7$83o1ufmX%90mct9sAQi-?#iY!L*OG^B
z5nrir@FaC7xrF)3JY9L|5;Q?B73)jt6cqAm#hePqu_Tx?ftX4j%MRH0lf<j0_*N^r
zS2&2u3J?2B6G;*lu2@-FtSjIaPW2Nz%I!y3`kRW93raPxpKK`>50^V6QaAJzbTLb<
zc1C6S%5*pka>Q2!5g(&W&y-~a1^K3-h~j*6Ee}+|BW;LK%Uv?v%xJzahm{x#q^JWs
zCF$a-T%C@#CgR=VJeXR#1g@*&rk<Z7Ss?|qxwK<*&EJYYlsPD9yPYq7ROTYSTIQ%A
z>o$nbl{v)j4IZqeEw3mj8>qFPPdQv!OEa!5D9c?^QjjmT{v)r0b%(7%%S4Z|(ZQrp
z6DoC=`^ZuZ1#}Vrl!>o}W$0LWrHMZyRO~3V*Gttbc{`?BypOX&NS(Qs2hgZOGu*~o
zR#3dn``p6w*1WD{qU1kyCO%r!=9QP0(w0c3yvlopnWDuh#r9%MsgrC<uozHkZ`;a;
z(1HxbGeLk>>??8P>!oI3bJNC@R21bdDbR@*N}O|PP>p;lhHJGrCQLnq7gy-0mt?Xu
z*$VP{e&AYhdD>d(8Ba26MW8ft(2fU5$%9Du8gXukyS_WXRGO4qr6ccyW^$QmKjN#k
zS~w-In5!$Nr&e;15MHL_&tVYfyqCFuqh&lg6=33MKx#S9N{drq2_`s~T$HSy!}$tY
zAl}^U7QST6t8|ss71T9qWHn!J=GcyC9bu2GU+x%7wXgEUsi-D42|myBaM!$|<>bWF
za>Y|iJTWCJCW-Tte8lMG_QCi0c7d6ysIFX!2VUv~b=sb9jp(#Ctu&*wf;L}G8Omt5
z9K6NuWzOQK%REL=s~LQ<X&2=l$xW7aHw$f{xOUliuPuDbw9uBBc0005+A`5_IzL?J
z(Sx8EwanF1Gq?%jC^qfA)Y%BGM8VHpv9H)MhT67$Y6q|3ZU0~|IkZ+fnK)0!PYh*Y
zMYS%Ex=0q}iHD0FM(pB;kV+d@o|ux6CY>+kqQ2NcoL}q_OLEfjh3!T2`1~TiblegD
z@p(r!CGuksA;R?J+~P8^r)czuXx=BV3Z=zBqqtK%T;wimO%hv+?DeE?UlQ4EjoY2s
zb7SJ-(&E$8xsL?!qgFw8C0ZJY!4o}EI?;~}ociTeTsztD4(GuWz{_1$&QFonfyI?n
zF}*ZDskp2_n$9y!j!O@QrBzu_1=lXnme-VM5%c8XVVfE}!Yd+#sHmzCZ!ER<py$TN
zA8PM77eNQ}maNtlh%HN<Jw}85z=pbHkACOsa!a(8)n&Tk(gNCc%PYmor4x9+rBKOI
zyQFw2Hj#W<cHGTg;FayPSnbkbyRukUq%EzYK!FCZz?zf~*QS)?>?$j-URp#ew7ha)
z^L~Td1iwUgY6|kW9~|I38kd@q!jfG5QX2S%fq_T-mKC3to;W*2TC|*x7<6t-Vn$kg
zMq14Dc<O8ik27%#7Mqw6o0P#7d-1qb3dc3GQ+VuoWq^lxbb3Ne8nxBT>p~~m%7_>1
z3N2&&c$leNzNCmpl)UN11MxG&o{XQHEvU~}S2*eD%%*WTEdEgK9(iCODn|{9%E?g8
z0FOud^LV5m{S+^I5-s))F`~xBX*rMgtxfU16abR`Gh%s-J8q$#t8vkH@uv>>DEfn7
zfgU{gcCl^nNhNk(Mm!!p(vlKW5I>R?MsBl`Ki>>&FHVE<S&4D+v(w{eB*&+io@_=A
zJSruoB!b0te4(O#E7eu}feJ}7yFd(CY4q0d=RHL!)*9c~a`<za)!b=SRrz>GtMaaq
zq<<H$uUs2xi-SKJ*ax%%bi+Zn7B2!v0J?y<1vuiOAQd<OIN~|50(enuS`{Ifi9f8G
zuFrss`3&LcA<&;Lym$Bx=%FoM@=i<KcsRY{egr?ty;>W1{o*h<bKS#$4A?LH_mD#c
z+FY?_?Y#!*ySQNM-a~lKT%WjhIiCNS)0h46w=B@ET}j|M^wD!>XIv7lcyz8VQ(SQ^
zuz7RK+v`BX96r_`S%`)XMa8CE#BJ)%2+OshXy{)hMWgC)<(QV~GxQt`s&)>4=MXyJ
zwCvJ5Eugd3`Yfl5jR4hx_+HS_@j07aVQBQG#-LUh`0TlbpZAiXUN4`uMZ*_ASB#)1
zx9UGaW}Kw*^9wI620!tte)rfe^rUXdgJE}|_>ORScPcDH50cMV;U;9|=U3Z7l~&iA
z>ueZ{8I!*MHPFfvV=F7r;MRjKF0G(<|5q`kXefTXdv$k#84M4~o!Pk<4SqH8#+6Pq
zxOJPwQctvVr*V?GhnlgqTGckX&Y7zJ-fqGwJg)cb{peUN6dbF#ylXKOj0~Aos=^RP
z-hFd-9Y)CK#l2Qo3T%j{!*{K)yy1JxWiOM$ldD?-Fhbv)kFf59VKdkIL?oesZ`T}5
z?*+~KcSzZ0$i;Y`aCi+PHPq$ek0qF*$@{auTnu^rmNUm!AH&cG{MnMY3kEQoji)<6
zF?3%agCWDCYc?K0gFD*Ry%UFq{%FpO&&G%tZcOmG00l+=dAoWW8v6R?mPvFWeyjbb
za!1tjtQ+;hDjMR4HODTZ;ryi=57wbWcRyU?xes(h{|Dc<Ti{Y>O}uxM4n6$$&94p~
zfa2dz-Tv<ZjL3>L89@_Zh;`A+N)>vJIlWW?y6ZiwJ13#oY{l0n%wSN)@=t$v1>L&m
z#EC<gy4{PDT+C4ajLTiS3oy*)+X+^VFf7{h<O{FCu#2;Hb+)6Q7r#+us^}s9`P;6S
zrlNvJZq^MuG-&tNC&TS9M8jRa_l$<6uZMloSpiz_boG-K$PHcQ+noW0zaRdfs}2T@
z$gLk21ch_o7*|a<rB2=dmDB3Hds4WZ0ebvMxcw^3b(dN5k90Bi{D!rTEui0ap0{Yx
zLvgBIe&A+uCZ|UyT%pjh`@hp$K%c+uvLy%>pBU#f2Kw1W*H30sXuK=)^9nE2b4%&D
zn*oC|obTGvZ|8TPh#Q-M4h;3VvfwqyyN1jvr0w9&@%MLMM1w2SwDavS!e+M<hh0Iv
zBV%&r=wC#|{8O1<bb#LZ{q~(ZL=WZWMw1V$JM_K|2K=EoXWm6ar|Y`03X1<ww41xa
zko5m4p5cM1u(jEE@d$bvrr2Lbdr;BGBgS^4!P5P$M^u>F`1OHDl29K`U092HE^uPH
zQ62iqXZkq&(E_V#>yM!e!~-Aw@=P`jd8fPcIt=kq|7$i4Qcp_g4cZ6GE#L0~f9JZr
z3p`QpU{XT(V$h;%yT|pSM-GW?TUucFuz70RR5;!FM78Ta7|`9>^<_8e7l(hA-2<n+
z+c<sANtCboUVo>e3kma#h}a@neAi>t+Bj6GSiI{-D4gezOYU*}8Vl?8@<9*q@9rD5
z7C#tfm6>d25ESOG&CCdZ!YyasSzQEqhq&ZN&7gOVt$QgHBl5z=4_976PcLVBTTewh
zmIps?O+ZI=tCVkS20f$S;&QhEiga3iNIrV-SDf=V)=*F|!!mv!8SqMGKo==IKI-`Z
z^t^D+sUM3lglwe0eJBizv)OA$x9heGZO&gngJ(xv3EG7bS<rsw-zqeCO5bzCi#L3!
zbs-wug;nt)b<}0~STD4v&)mMnr2z@y>WqXq^kiMn;g4Q}^Hn~7Jm41S#V<bY>_r1H
zYnA)0p?K|-%zz0{<bUF0t00U-&>GKodqLO41?5(tBe#QktaQ*5Gdg{LD12$xH-BXG
z!tlu>#$CLFslnF!`33mG(pihOu4td#u!{OK6c+6-nKJAG6n%2P=}T8AIBhj+!68&=
z2pVqDj1J%Za7uhP=;X%ePP%~3*z9um3TV}C7c)C_V9JP<mM2j!^YZSv#c24C=G}1^
z5dNV9k?;>wJ`R)|+8yol&uM&<RlkG6D*k4Kc0YO>LTkGllr|3?Mu3cohrzVV6@Z>Y
z-Uv$j{uiKh!qcm3TEa#+Gj)RA7SnWn1zL-|A4ZB!#5g??w42c@SQ=*f;~m<L3(zCl
zL{_0kw5`4XN(abqptPyn0VM|`N-KpZ`NsoL>OH-lrR|z1?F|8-bkx&(SvpZSfRdx?
z6H!Qxb{LdAl_<pkmQY6fI#HVUGEh2L=!Iw~C>cddk6!-MiIz74#v;EAlpI(GN{&cx
zJ!#4P07^%=`B?ZADE-U;)1_w-NZbLV1e8vsEugfdvc_ZXl@g`3n(qYzF)9w;P=Nd-
zP+Ge5qLa>x`=AsHg!-T!@=2hyjpu;U30nb5j=KevR@(ER3FesplSt4udKHwGNUSgB
zA9;GMNozD`0u&+N0!ohe6DS=pb0)$sFkQ8v6eGM0N)CAmlwt>Zxk=Fwy~w14jb35W
z{%`3I1Cj3zfUoJnD4qoCz@T4H&`QvQ(h<8N5OasT3LZ$iAHB?^O^RMz(&j^y!l=!l
zw67aM=>*&fN(am>P}=wD)g^6Ot)R3me+x>xBE7cMQ;;zq2|DREfKoVC2TI%UUQpT%
zTR>^8)B8(0!+!*&-H_f{(*CXqg$(#aDejvAinE=a0;Rao2|w28#wwvd5~Dq3BxpPG
zRbiNaI@9Ub9CWhLj~Z$7p`SHUpy?lh29fUqrCqNAFFfhs*$J8o{uxkypy1aW6eG~D
zIw<~&1*JGI4wN<>4QMa&^FTY0KLASS#NkNHKOMOpVC;jyDE#W40?_546t|rNr2rB?
z2VuKVVKFG3c<+HmBkz>}=R*DjC>_05KxsQ(ln7bSJ)jg9HiJ?yLqFx9XzG7wVakxN
z)hEF+ETsle+Ait05p;yoZy+e5rQbT#BELHsa#&V7Q^11)`gCIGYd|4_7ho7EY(W16
zr4#Z1QONxZ^dj<afKtf*7AOU*M?fj&(7%HOg-=IG0E}ax6i~hkN@3G`pcFthgHmjO
zzdT?Rc%B5MnBhZEI(S+@k05^rlp^YLln1>4N-;(&D1~bmDGy5XkAqFmqG2V)0I{GH
zP~z_q7=_pxP&&b8g3?)@0!jx|Drgb%X`pmYWPnm+n*~ZSKsM-9(D|Sg>E?jaxv~V5
zB59f~ik{Yh>MSw;uOdP5-F^~)LYkip^!yko9i10I=|m&C7*_uWl+JRZ6dhdzT?PI(
zRE~T*Xan+>Kq>0E0{R;A--A*(*8$3(wm>grVorZSf`W(NKq;zGW7sH`r~SVLc{`%$
zkv-@k^vId=p!Bw!&T=;lCmq2apcGn<HWMeM`zUPj22d+LdbTRk1Fd@qmdq0#?aI?u
z_}wyiJZ;Su5Ato;y1}%Xy+~>C;8uUVBsrV~!9+=e9iIq^KY~>Z^6gn2(ilFp=)hhc
z<U8WeJqPMK@iCKRoLMLMj$Gb_AAyp7SLTTBN$HW|ylqoVHjHK$!N+Jo{}|RWDC5a`
zk(TTk%RO33k7H9YERvq_EE{R5UHrg%knhbl52k(CKBT3(zN}@CKS9rrM@i8{)-zb(
z$Lugi65pS{>zC32ED3z6u}S>>za2MvGOHMr59IIvC4LawH^`sDP7bDnSvya|Q$2(b
zepE^ggfd%rp=4<ofB7%*!&wseQaXY!6)8QHZ61`5<V!~4N3oVc`DyIRU^<%hAT1de
z!>s8?0a9bJ{2Z0i)A<huBt>zoh`f^bGM*oul8lDE2EH`KGuX*NJqi4{lw=ZFFVz*x
zw>y|7I*Db&w<T@K`1`VfbP8)2OwZ=$og|aW&VetPJBM8vlu2VfgXwf;hxH-JXRv_5
zbS6t0OlPfUMT42SZ1Z3`n=dZO+<E-Gqx5*((sV#(6&zxs(BGepg&YmO57I9peQ`8i
f&?8+kNpc2Xq}L%0n^+Lin@#+b*nlt(oU8u_r2CQI

delta 15694
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

diff --git a/16/DOS_GFX.OBJ b/16/DOS_GFX.OBJ
index 35e3f4ed617b65a74bc2c2ce1950811062822244..f17a0b16baf7f45788d4f3ee34931c1803b59d5c 100644
GIT binary patch
delta 3006
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
B(Q^O*

delta 2788
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
O>V=3F1hq19`F{altb02E

diff --git a/16/Project 16.bfproject b/16/Project 16.bfproject
index b5009ceb..378d9de2 100644
--- a/16/Project 16.bfproject	
+++ b/16/Project 16.bfproject	
@@ -1,7 +1,7 @@
 c2e.convert_special: 0
 e2c.convert_num: 0
-openfiles: /dos/z/16/16/dos_gfx.cpp:8135:7436:1:
-openfiles: /dos/z/16/16/dos_gfx.h:327:0:0:
+openfiles: /dos/z/16/16/dos_gfx.cpp:1620:647:1:
+openfiles: /dos/z/16/16/dos_gfx.h:665:373:0:
 openfiles: /dos/z/16/16/dos_kb.c:1039:46:0:
 openfiles: /dos/z/16/16/dos_kb.h:23:0:0:
 openfiles: /dos/z/16/16/lib/lib_com.cpp:0:0:0:
@@ -80,25 +80,25 @@ recent_files: file:///dos/z/16/16/xx.bat
 recent_files: file:///dos/z/16/16/lib/x/MXPN.ASM
 recent_files: file:///dos/z/4x4_16/!/c/TUT10.C
 recent_files: file:///dos/z/16/16/lib/x/MXVS.ASM
-recent_files: file:///dos/z/16/16/lib/x/MODEX.H
-recent_files: file:///dos/z/4x4_16/modex/DEMO01.PAS
-recent_files: file:///dos/z/4x4_16/modex/DEMO07.PAS
+recent_files: file:///dos/z/16/16/lib/x/MAKEFILE
+recent_files: file:///dos/z/16/16/lib/x/MODEX.DEF
 recent_files: file:///dos/z/16/16/dos_gfx.h
+recent_files: file:///dos/z/16/16/dos_gfx.cpp
 recent_files: file:///dos/z/16/16/dos_kb.c
 recent_files: file:///dos/z/16/16/dos_kb.h
 recent_files: file:///dos/z/16/16/lib/lib_com.cpp
-recent_files: file:///dos/z/16/16/lib/lib_com.h
 recent_files: file:///dos/z/16/16/16.txt
+recent_files: file:///dos/z/16/16/lib/lib_com.h
 recent_files: file:///dos/z/16/16/scroll.txt
 recent_files: file:///dos/z/16/16/project16.txt
-recent_files: file:///dos/z/16/16/lib/intro/lib.c
-recent_files: file:///dos/z/16/src/lib/dos_gfx.h
+recent_files: file:///dos/z/16/16/lib/x/MODEX.H
+recent_files: file:///dos/z/4x4_16/modex/DEMO07.PAS
 recent_files: file:///dos/z/16/16/lib/x/MXBB.ASM
-recent_files: file:///dos/z/16/src/lib/dos_gfx.cpp
+recent_files: file:///dos/z/16/src/lib/dos_gfx.h
+recent_files: file:///dos/z/4x4_16/modex/DEMO01.PAS
 recent_files: file:///dos/z/16/16/lib/x/MXCR.ASM
-recent_files: file:///dos/z/16/16/dos_gfx.cpp
-recent_files: file:///dos/z/16/16/lib/x/MAKEFILE
-recent_files: file:///dos/z/16/16/lib/x/MODEX.DEF
+recent_files: file:///dos/z/16/16/lib/intro/lib.c
+recent_files: file:///dos/z/16/src/lib/dos_gfx.cpp
 snr_replacetype: 0
 savedir: file:///dos/z/16/16
 spell_check_default: 1
diff --git a/16/dos_gfx.cpp b/16/dos_gfx.cpp
index 41b7d533..52e259db 100644
--- a/16/dos_gfx.cpp
+++ b/16/dos_gfx.cpp
@@ -48,10 +48,11 @@ void setvideo(/*byte mode, */short vq){
 				mxSetMode( MX_320x240 );
 //				mxSetVirtualScreen(SW+(SW/4), SH+(SH/4));
 //				mxSetVirtualScreen(SW*2, SH*2);
-				mxSetVirtualScreen(VW,(VH+(TILEWH*BUFFMX)));
+				mxSetVirtualScreen(VW,BH);
 //				mxSetVirtualScreen((640-(TILEWH*4)),(480-(TILEWH*4)));
 				mxSetClip(true);
-				mxSetClipRegion(0, 0, VW, (VH+(TILEWH*BUFFMX)));
+				mxSetClipRegion(0, 0, VW, BH);
+				mxPan(TILEWH*2,TILEWH*2);
 				//mxSetClipRegion(0, VH+1, VW, (TILEWH*BUFFMX));
 		}
 }
@@ -212,17 +213,17 @@ short ding(int q){
 						}
 				}
 				// fixer
-				if(q!=16){
+				if(q!=16){
 					#ifdef TILE
 						if(xx<0) xx=(VW-TILEWH);
 						if(yy<0) yy=(VH-TILEWH);
 						if(xx>(VW-TILEWH)) xx=0;
-						if(yy>(VH-TILEWH)/*+(TILEWH*BUFFMX)*/) yy=0;
-					#else
+						if(yy>(VH-TILEWH)/*+(TILEWH*BUFFMX)*/) yy=0;
+					#else
 						if(xx<0) xx=VW;
 						if(yy<0) yy=VH;
 						if(xx>VW) xx=0;
-						if(yy>VH) yy=0;
+						if(yy>VH) yy=0;
 					#endif
 				}
 
@@ -272,8 +273,8 @@ int main(void)
 		// main variables
 		d=4; // switch variable
 		key=4; // default screensaver number
-		xpos=0;
-		ypos=0;
+		xpos=TILEWH*2;
+		ypos=TILEWH*2;
 		xdir=1;
 		ydir=1;
 		setvideo(1);
@@ -319,21 +320,21 @@ int main(void)
 				mxPutPixel(VW-1, y, 15);
 			}
 			
-			getch();
+			getch();
 			//text box
-			mxSetTextColor(10, OP_TRANS); //set font
-			mxBitBlt(xpos, ypos+(TILEWH*12), 320, TILEWH*BUFFMX, 0, VH); //copy background
-			mxFillBox(xpos, ypos+(TILEWH*12), 320, TILEWH*BUFFMX, 0, OP_SET); // background for text box
-			//+(QUADWH*6)
-			mxOutText(xpos+1, ypos+SH-48, "========================================");
+			mxSetTextColor(10, OP_TRANS); //set font
+			mxBitBlt(xpos, ypos+(TILEWH*12), 320, TILEWH*BUFFMX, 0, BS); //copy background
+			mxFillBox(xpos, ypos+(TILEWH*12), 320, TILEWH*BUFFMX, 0, OP_SET); // background for text box
+			//+(QUADWH*6)
+			mxOutText(xpos+1, ypos+SH-48, "========================================");
 			mxOutText(xpos+1, ypos+SH-40, "|    |Chikyuu:$line1");
 			mxOutText(xpos+1, ypos+SH-32, "|    |$line2");
 			mxOutText(xpos+1, ypos+SH-24, "|    |$line3");
-			mxOutText(xpos+1, ypos+SH-16, "|    |$line4");
-			mxOutText(xpos+1, ypos+SH-8,  "========================================");
-			mxFillBox(xpos+QUADWH, ypos+QUADWH+(TILEWH*12), TILEWH*2, TILEWH*2, 9, OP_SET);
-			getch();
-			mxBitBlt(0, VH, 320, TILEWH*BUFFMX, xpos, ypos+(TILEWH*12)); //copy background
+			mxOutText(xpos+1, ypos+SH-16, "|    |$line4");
+			mxOutText(xpos+1, ypos+SH-8,  "========================================");
+			mxFillBox(xpos+QUADWH, ypos+QUADWH+(TILEWH*12), TILEWH*2, TILEWH*2, 9, OP_SET); //portriat~
+			getch();
+			mxBitBlt(0, BS, 320, TILEWH*BUFFMX, xpos, ypos+(TILEWH*12)); //copy background
 			//mxBitBlt(0, (TILEWH*12)+1, 320, TILEWH*3, 0, 0);
 			getch();
 		while(!kbhit()){
@@ -341,18 +342,19 @@ int main(void)
 //			scrolly(1);
 //			vScroll(1);
 //			delay(100);
-			//for(int i=0;i<TILEWH;i++){
+			//for(int i=0;i<TILEWH;i++){
 				
 				ding(key);
 				mxPan(xpos,ypos);
 				//for(short o = 0; o<TILEWH; o++){
-					//xpos+=xdir;
-					//ypos+=ydir;
-					if(ypos==1 || (ypos==((VH+(TILEWH*BUFFMX))-SH-1)))delay(1000);
-					//mxWaitRetrace();
+					xpos+=xdir;
+					ypos+=ydir;
+					//if(ypos==1 || (ypos==(BH-SH-1)))delay(500);
+					//if((xpos>(VW-SW-1)) || (xpos<1))delay(500);
+					mxWaitRetrace();
 				//}
 				if( (xpos>(VW-SW-1))  || (xpos<1)){xdir=-xdir;}
-				if( (ypos>((VH+(TILEWH*BUFFMX))-SH-1)) || (ypos<1)){ydir=-ydir;} // { Hit a boundry, change
+				if( (ypos>(BH-SH-1)) || (ypos<1)){ydir=-ydir;} // { Hit a boundry, change
 			//    direction! }
 			}
 			ch=getch();
@@ -360,7 +362,8 @@ int main(void)
 			if(ch==0x1b)break; // 'ESC'
 		}
 		setvideo(0);
-		printf("wwww\nVirtual Resolution: %dx%d\n", VW,VH);
+		printf("wwww\nFull Buffer Virtual Resolution: %dx%d\n", VW,BH);
+		printf("Virtual Resolution: %dx%d\n", VW,VH);
 		printf("Resolution: %dx%d\n", SW,SH);
 		printf("Mode X Library Version: %d\n", mxGetVersion());
 		printf("bakapi ver. 1.04.09.04\nis made by sparky4i†ƒÖ…j feel free to use it ^^\nLicence: GPL v2\n");
diff --git a/16/dos_gfx.h b/16/dos_gfx.h
index b9045057..231c1061 100644
--- a/16/dos_gfx.h
+++ b/16/dos_gfx.h
@@ -21,8 +21,12 @@
 
 #define SW	320
 #define SH	240
-#define VW	560
-#define VH	416
+//#define VW	560
+//#define VH	416
+#define VW	(SW+64)
+#define VH	(SH+64)
+#define BS (VH*2) // buffer space! not BULLSHIT
+#define BH	BS+(TILEWH*BUFFMX) // buffer resolution
 
 //void drawChar(int x, int y, int color, byte c);
 //void drawText(int x, int y, int color, byte string);
diff --git a/16/lib/x/MODEX.BAK b/16/lib/x/MODEX.BAK
new file mode 100644
index 0000000000000000000000000000000000000000..560a1c68304c56844f41325820f296a21192ac4e
GIT binary patch
literal 25600
zcmd^n4M0>?+W)!t4#S9uBPvmnf|;vPq*8`L%I5$r3<TqVR%lkN?Yh>hK<@51prFEB
zGqw+_ec4?NYkSR#cH7PDV^IchwOX;=v~1JFbOu}?bper>|L-~X-eFMdeX;-h{~UPk
zJ?GqWo_ju?^PJ~A&vS0qD8?2s=Eu}uSpYL+<|igb-M{LmpHvzctJP7IRfZ!&n5B5-
z(nrD*R;_yIr%RVVv@$&0`q0W%4?nUZ{I;l>&sQ2*ynA}afn+a&36*1zG{$@&c|>Mb
za!P(wa*8RlQbJnB7Ll=K6x{aomLTSznZMYQl5f!^A=^Kn^JmL`D~OViyJ;>PpSvJ2
zEh{H|QI^?~kdcvYPDwYLve;;pu%;)cWaXx$W~P`eJRxzRB_%gIC5LjcXRAjuCQx0{
zEr}TxRR3(Hj>W$q{BmopATYK-K2v@sWTI7{S8fkvMc2qC;}l7@8p=*c?;K@w_ZCa<
zL^IFF(e;b{3ns~5-M2rG$pr@4q?gTsF2*WNXDSQZs?32=+Zfw?WOKc23X1BP%9vbY
zZ0Ts}kh*q%B<=D`=<IhCo(VWv6t>$b)rp;yJ54qRSo5|^T~cp)aqr>+Q>t7Lxc+F-
z4al-f9L@7YHpo_Fk`J8Y`R*$I*Wv={oOIDq*al=FLy>8y_#5Lp8&E^})0Xy@_OdUf
zI>RB?`+8QjsP~|&{9|S|uQ~s%HLfb@M*Eaj*bOb6EuB(tmHj;LnMzZaY&H<WF^7&<
znmYQMOlNhE7xd09pU;Z!b`*A$og7^!qF$Yj!mc_Us?v!T(5q%g`p=d}x46%}*wUi4
zrXwk7z|>V%*d-N99#i*0Q%AY=Ji4x1wx1s`pDq56hT57~<_xn4&KoR3#hrRVaNeaC
zM5k3RNY2%Csi8|FUHb8$(ST567+rpZOPvGsRfI8D=s78g==pCNJtrj%m!1^_*Iqq6
zZ}0;>FWaOL?hrb?jFLxyw39N@v-4*%Ex2$nm_KVUbrx%_9t$E5%*Q05B1HHXb?na?
zp?@lY&;wXJz{*Cj<;>%uco|>|;yZa<&+3_;eFPrxIge8wUpT`$*w?I$oo78vC$zCK
z!Z;y9n1#^ofLK5pU@>61uu*W}-o~nhU-SE$!XDvs;h50PWAvnrN#Y1GT#OY_4xs%l
zMz}<LPJGcPt&P1aek^)KQ5r3^u`p?}G)J-^bU$D<;0fs+X&>%w><j6<)Z1{Op|`>P
zE6M!_$?cL{zm%e4XEV0uwEL*!+NwrAbAKecUzc1(O5DER{et8wS0nGapOH9@Q=+R?
zbT5}&{}7{MCo*PpyPuU@2i3^uE(Zz(F=qdpJ56%Ett6K=y7MI0PBpU2b(fl_&OL=!
z&HbwA+9A3ximvS{o_2Sl<a$<(eBruXDX`{{`>^OLQ}HyrMai{FjqG;)3n9FC&1>#I
zh}2$pwdi^rY4cFWuU)@Ih+6!W+bz0El;qOS+}lOh!=ih)=z2iS+3YG-a@yZ<*NUzT
zHD{gc=W6nH_a=_s^$&r!f6ZC<4@B3!%2V5E*L6yXHAmg=3a<MRL7i*|U6PvYbiXLL
zUQmjbzU`WVWa`A%dF|{kxo=gF*Lacd7hJ7~pzc8a9ztl3{iypFf=j0$FFoj5q2_kF
zYXsLH)!c8p@|5IK6}jX(q~@z}7YV$J?iO5Tr136t+XPpF5-C0DmIc>sg8Mze6{S9J
zaovj$bz!snCBb!#nsc}7el__u_Y)kc%gK0~>}TC)nJY<oT6)^`6_W8HbWAOCJ&0tb
zW45Tdoo**{RVfkM+pdvnIn*8fW0zbn;Ss&P#yw4W&Ck?=XWcS$)hkc&8apelc~W$W
zV2^r003a9;0=Nz^888)a6CfUt2uKE)0BL}`02u%?ARCYaumG%pe83{Wy?_G162MZx
zgMdQ7GQf`k%K<9@j{;T#iU1{m)qtM^Yydl;46qJR0oVYj1ULYj0Gk2TfF}V@1GWI3
z1N;h51NaSKE8qpdcEC%3mjOEfI{~i&>Hxn7yb1UdU>9IF;9bD`fO^1QfD_OJ*az4T
z_yF(`;2_`-;BSCW07n3y0X_$O0XPmg0XPXb1^7lU=o$m)a-Ck#H~xSw2^2NcC0{T2
zH9kaXE9qjR=oWfVOP5z^dD=}6n(5L)(XZ&zNl&qi`8AD3wCP$rZJJ8a85AP)O@zJ)
z=%ps0mzo}-3()JEHqe8|DfAl(y+WZsQrW$9`GC?srAsS4Xrs${M4M^7Y#xs+&C@6}
zi_+#(G@U|=kgpjFslNH&=&7A9l@xu3p8l3XFVUrrqI)Rx5iX{!e-wnjgN^a&+rH2>
z0E)#7C~a|NsD#|uzS#A&O2_ZGW-F<-Hx#m$Tpz00e$yT!H$^r?$svqI9`0$A-I1L=
z-$+NIWT5VC_|9j0BAb<RAER7HWIM|BM#-39DED2@8X}vNaxEy=8R<s3t|%GRN4f8M
z)*QJ<DfbD=wMTZK+`cFo(-`Hx<Jp4f?x<Ka&+b?Lk)b_+hu28uAL)3PQL0F(ct53r
zQxJ>Lul=ZuQ8FTw93K^{S5SmgD#Da%ln2UBk6wGKi;*N675grRAT&yTQ)Dftr5+i*
zaofgEJcs0F`IGw^?z_;CTeF=xB@Dh3<mcxk@^juums>Hs&e?Q{r)Va~z*#_-hbiCB
z>9U?4fW-CAZIti#ba{`mfFL9%D9_IcqVse93t1ZVbQyyzjg#qeGeu)4l!z=egCv?k
zdYVDHMv%B)<1Z);{GsuAi!fai>LAx?zcRjGNlGR8?x0t`OC7d+#}SObdiicHgM9aP
z^*BglqcZc8vNE!AELo{J2@6qCizbfEV-UyqzJt-eLpJMMBN|HropwY2JI`kB>^?0Y
z+}YhK9o+e5SocY3ufzGujuUQe`w_t2`}X!{Q2P&f+n+J)_HzWrt8f1iYX5})2KiRq
z#3iNYBxR(aGX<?PKlgT~IMJFHjh%yGm&78QBb%#C15ukXL1KGKe<C-@$6SvvxvA#}
z0)+_3$9j&s?o(3`%wd=ZU$}mV8}fYNO5|}on4_j37{z4M!1{XID7m@ic+2rybZok5
zAWLqdh@YMbrU6s?FR@cpHi`x&6$DBqWtQ5a`D87<na@t!jr>+RQQ2f2piP=|1iPwT
zqHyRW-#wZ1mHrKXteM1|6KKP;m8Q|}Xa>E8N#O)%*E`?EcIcl9F{t#PL*w7*9sitR
zk3UBcaP{MVnD*-vHjQCHw0prWUfY-7pzKi84N7`uLTXB+z+SHg=M%8?NlmfP#w8~u
zH9gDxC3vRxAlLW7R>p3rHll>KA<CbnW2|Oq(o9gtwjoIiXJQxlo1sawz$2fp9s^tf
zYMm0Z@+$>)P|K#)Xc=P(T9R6qYZ<Gk#zhFu%tuo0!rZ~CKf>5TjWYKN!nN8o=Y+V;
z$mEH^Ob!~y<d6_nhUK(q^fm($1CR*4LP!v+WvptV$f|;LtSUs$947q+eJGoClB*s>
z7PXZk2UO<4u}0U|8dxnbm<(yPKw{FT)dsO$jAaM8$~?TBZb&s`Q(!G>VhX55T}%ea
z6qr_v8kzK<)wJ3WhF8Q1#eOKB;EAs12n;F$eO?qA;j{-&t@4Z77K~634~=6{k$UKT
zob~`7521K4#q|{Dm0s*m+7lzgdMD2lS#0x~agn`|hwXP^-u3l-DR;?-qqd=i@;p5r
zmPV&W_C@xt5v9X?v5!5rW>n<G$iLbrNIiTNN2-p+9xEN0isTE(_g9kgHPitd^*mpM
zGcQ9pk|VtKJJ21j*~OfY@&xB7$b4e};{n$KCIhAdZURIBW&&;p%mLg9NCw;uSVDy#
zLVyJ3M*t)o|B@1)Mc~(f-vQnLkmO1dC`p_oVYUOh0T;3A=>gXOZUx*1Fah!a_X1V|
zAYC`E2LNZ|OMq7_!V^PQ357qHxIXWY#ve?>*5@e*uDN>t;Gy;5{3g@odb-Q>A3pQ)
z+q8chw3%s2&&a_1y%8HnZT3l|+;bd<zUdX{n|3r*`b(dk=xdOB98)TFrV|$$96#Vm
zy$yUa8Td+EV1)XP)MnNI==N4g?mAY*gHZ5Qng%Kh`?=Dre)Ez3W>eot)@<s9rq860
zlO79;V@06{kJF#yc%4LwFJuX$EWylCH~@9sHLALfq*>_x<YNw#!DH=9#S2@f;2A0X
zkR%_&>+|G`9&0b2L`hh}?ketDEZGAch5bHSze~`N)=y%czKY8Hnp;^#99E8sR9ZAF
zw2%~lq#gjQ1#AF3N3_^Pmt(m6PNf=^Ub1ODaeC<`d${X~i6a<s_4Klx))TWPPni;u
zQ?e5>QY@B~IgH({4fV@3)Jcy#`m>b}|7clJ__PP6htHfdXVxva+!mgYV@b~qUlp}7
zYI#(6!t&+eJkzT1l@G0YXl2Pm4@P15*PaQ`Tk|IBn>X}c5HOy`8=0rb@P^@IR~1qy
zKEU1(K6Z_)FP3)AU{xEsFT_`F=)2Igq5p!=v|-=^$^_lXgq4!}O$L67V2N=T6CzDP
zRi;2H<*vbq2g-X|j!XMC9o$_1`1|Y|BDF3gG&Pn4OI`h%X0*p-6j)KXjF(gbHNC@w
zB2X=Bg`jxe&K&lDveWY&1%|TL`Hm8O*{S)CEdv*njNtI{=I#rR|A~ErGJUS;EH?*{
zK6+yT9`#;u-N_c+BW~%xFtEArLh)byCoL{exO4vk*|qbg=I*xc3u5z*oi{b`Py<3u
zJk+!!v-sG34UXfxKa<Y9Y$(2nOVPy>=j8*t_el<CM`C~9&JOxJ(R;CBceB)ynAm@2
z2mPJsZ5ZL@NeX?Xa(%2<UQZpiK2|~SJ>>OB;z#=wIY5y@NMwfuk*yKetzP*O!n$k<
zR@&595_G0g*H{w3uX<b+nJ<WC@iwaMOQ-p>Uz<Ov>BF5rsT{%RtDir+seN-c&18YT
zlGlI1Y-0226E3ZxPnK(a^1ioEj0)Qfgfs!OfNa$(Y_l3{Q!kXLmXLFbAp~XxF0hof
zN|gm?hgc^549mnlie(}zYt4BW6}rf%u-RmE6rSa#h552QNHZtsVIZ*P!I-eUyje;w
zz5tVm-4G>Vt9@7TX;>7T-A-MR9`=N?ldviT4Vb%%-|=OObv5Hz#Wlq8en3+79mE!&
zL@3uwo~pedHIv4#$vb|T!yZ45VC2=0-y<}B71iS*Z9<|>O~}klNXp8|NlCKA`xvrT
z(Ri?cpfO{|UlV%Wgs|%;g-1-jVakm+PW{2O>C<nDy!qx^qM~k{F=OV;S<%tA-FEx!
zvuEFNM@-C|IdkX6#>U0ndFQ-&^XCuUkcKE5(svl^m-k42k@oG3I=tgV-{3Cvjv7Bk
zn!+w$dgtuE!P{TMUN2HP0>jn!*EH&{1Ik{5&u4YHK=-_>QSZ%O>Sg*oNUYd@Lkzxz
zS1Hn}f$0>QQ0KFi=;1wY`>eyJ2aZ6z`u6FleVsn-v!>+aV#|c~y{NU%K<(Q#O*rt%
zrSzP}xA$IpP8+s<Ktb?5=-Ev5e{oar<?`R#)nOp=E1P+P89S-9E{D@PlbA?>pg^=%
z@)uQW<weC<S>7r|IW`(tOKVi*6VQc?mOq8%Zt_MW_D<1%X%CV=<vD&A$XeVj?uG|y
zLYNaeP{Da41frV(cK}i?!d!0$D&wDS88ZIqmf?=Sg5Z0M{}$@M`>J8B7xbC=mXw^#
zrx-h<#na8{mOB|UY5c->2Oi7VF>O;l#AFUhs$A>bUs0cO8-4ilhnKFrf921@Zwdca
z$!hsSt5)5=;=z@Vgy%l+NKw(lY^$o)($lKYY#Q)*noa#|>n3yGt_>j{-U>nJ+Fb!`
z(}53XuAE$D>f0r<ci2`$##fp8Hy8A6nivZ~s=sy)gysQ~s|Qqeb0E6@z@0Ut*uGed
z%P#;BUR%6l1KL;lbq1&Jz1sZD7&d(?2>h>pe%?*v^MXp>LmU$tH6b=5D<L@}!IG4g
zl8cJ3*SdZIb^SyuN%00xCrR?V{22EE*nH%DkLNAJ+Y-aWI-TRoPQH(DobGh!vMa+J
zeg`{Ge1)fP8MO5LN*&V97ffmxQ=@0ju^{czA>F0*mzn6f-rHa1;nH&kN8oq${q-vt
zb%nhD27RGAL&y?tU~Hq-%fAuP%X@_$;b!pxk*|2c&>BL*mkYFg-&3^jD`)c8TOym*
z=r?}7@w1*Iq)H?cfV?-dVU4cmQ%dQtGM|?l6b0T#iiE=zcw-KotSs!nP^g0!eH2O@
zYz~8`NJF=WNlBn^+1wwyXO)lyR^@pXbZpnNB7clN?H|3GL}+z-<+HQu6*GVss2CLO
zVj!%dkb2gLfv^@JfD{89G$`Xdo{WqLC>gPhR5Bu<WIPKOjS6Rx<bIU}9LFAID<i{5
zm8qNTDpjWQ4%69+`eOf$f8F@S22<C|LeVJN{gPP)NZUuhEEY}oN$6Q|zQ^7z9jP-Y
zn$DCuR0{91#m%a3k9k?AmWGN3iR~kKNhQ*=qPxcq!+o7nUE9by#eiHY&Z_5CEFKkb
z9M$|c51A@R%_H~r9BcWq%G@XKYdKzJ>a7#ud4jzVdOe{sEWK##L1+0VtW&c0*}9~X
z^O5%6c2|RZ0fmsekG5ebg#0MQomG@V$Vny6DTUQS-|;3#+$HboP~UaxJKv=iQ{VRW
z;M-0$+)z`=oD2+31n2-z{5WA55u90c`7ueVuz--}mpi@qk$FYuJWSf)uPCj9G{ik*
zHeqByp}l`&5?x@k@oR(vz_0NEda#_bz;L5$TuYaYl(v~JzoyKv>G^dIVHnE#m&Mn=
zw={l{HSG0ILC}9ielb>c8ygAlu!IE}mMD|i^5lQbOKkrLaFOs$*I%Y}4#>>UUSLu7
zFM%2ZhGv(X%yKO$*)NZPf0$~lfht!^t{TC1XsV^G1z^<)IUg8Uv$m|NIk|P`6$4Aw
zvLf9C_q0$0TcIVPG$G9#!6s@f$VJXL+RwiB#kDU!zt(Q|9Q7PM?XfQ(7#Og{7@0A~
zrrwQ~0gG{f;sZA001J(?+v7r+=XAr`wGF2|EUqvyu`rH#8lHdez2_S|{*vG7ii(QW
zwsq^)*^Dv9F#H*fGiJ=2Ja6*ksfA0PUle!xbljrnnQ_LWU60N%va<T)UB~Ooj4>9Y
z(Gp`!qaRCS_9vfQ85|tU;wFbqnG%{D$Ll+99;0l?H-HLKh%p|;-Jl!Lfzh(?_<{Iv
z%3W4g){oniL{H)ric<^d&YML6{zGwKLHQ{>6K;0=O~HGzW5%IAOiVTy!xLFda?Fya
zD~nioc)U_BJU%`?92)0vl&7>Qq4rQhVKmyPTKtD6xKl0EA0Fs{F20P}njBBQ&}2h5
zPz7Sx>Iz-x5>y!X7+u9`7B(fhVn7$f`pbHC6klCY){Aas{W?Mrj(7$A)7_@S9WNdP
zyqDe*Zln&u>+w$!sweOpsJ*szyI*?0%tqz=F<z{<qJsVrN527IS0z#_yI6l&Sr>Jr
zaxbIjHS}IQ<>g|i`lx@H!C<JYe3VsGRv)jftf1b<ub(yTcoLMbj;-7K!jp~->*#&>
zt>*7T1|EO9vV_N}9PqEE_6%^mMtTp=&u?in7$JLdM-y9@Jk2;Qc^ykmPNpg_3_hAS
zz*b{e;^WaDWz=FFTa9`d467N>td0V1o^Xtv@{7^MCEL(J@vD=QsUPD|K8`URk~!JM
zB-<z+XpE!x;5m|YF-rbq>UOFr@}q<<nbNbDWT!DUgOVx#GK(b{`54gidkj@siKDVA
zJ{@ECF2ReD9usfVp+1;9Mq?=ARE+ZDHjVHlCtEDb=}sM>q{mSKn+_#04=~$|7<iO^
zeJiH=Nr{3i9LPWx4?c$y^rQY*H^6K(O7y;IyeC;4v!S^*W?!px3nl{Zp4I9-G*s;_
zwz{lrwIRl~PU)UBOc3fO<Wst9n$j&s_0DD}@iYuD=!VUhq1<CwKj^C;6|x)bX?A9>
zuI{g{{td`e>85GGN6mj!y~iXg^?a0WNaxi?^9e7JRT?Ll)zp3H%@|`$a{Tf5_;vls
zHcU&K5oGP?A#w~1HiphHRxgQD+r>ha`h}_Q2~+W7g3ybYjU_*5$w+2kMiUu?kFd#;
z!|0CD506ibqaMW!p&P>t1vMq7<wd0G{Bh5jde<aTp%M(=l(g!!Dae&JC3p&`WOAkQ
zw_u0zcl5EN9R#61zg`~h4W;{R{JH`3q5*!_(!2GPuKn;-jd$yb>rp!0LxH823gf5X
z4Go=yFuelqmi*_T2!4|QltAeeSJEf(bi#KBU1r}gV?Hl6e})q8;rXdlkNTX_DNcB1
z&+g&r^fo0vdp6zqbM1Y+-0azemufMIKUdyM!TIWQ5AIYet-e~jsNNp+NBJq(rT#{%
zKT4x#j4ge-^68}vgwa)5*;U4RD``ex6qSXjzal<7zM>yYL7TRq2Aa0B(}=GyqA)O^
z7*HR`nzQ4Iw6qV{YMqvU`IAr5Y-Mwk7frsGg@(tkjt>vz)Cz(n)=Ym`R(iqIdofMH
z#z1YjVh-DgPJMpWONes=7@L(r|3s}Zgk9dM7lnQP2q|Mm0YDJym^Llc5Hkfo#N%{v
z;hb1m9DYdf{tS%P3a}6UM}0$aRVBx@rqJoHuP=^=qV-OJtrVl{$>~5oB5!1dTD@Tt
zUgg**8fKlW4KUP>GdP}=470kcLIMpvCu)Nz1!m$9L;IXv9uM5t%P$%qi-NYcyf6H*
zsZ|pL43txD@bhOaF8bqz$U>}#r+Z+n0i}o7fhVd}GSnK$6}~oD%fKzoYtM-A#el82
zakk!o&Cjfp*d+xSq%PI+fxT3S(GayQ&``Bu;2UhL0t}8gQ~3o$iR1_~Irg@+t`r?j
zQ!D*a(~H0MY##Wg_~_#sFr%_PB>|oiLzHKB09^v<5^M-^F*c~()oYz*Z7k6{bQSeQ
z;U-T>AWFiXz0?!6ZJa?c!C5~9w*Zd&v*>!wUt@?}9XdgD8?`RPFw}}}B`nbWSLp~3
z-czM&{|)RHHQSgo1`_%_i?A;qcX-eV&SC^s18e}8YMn6EatBCqeuPsKHwBZk<8J}v
zxcDxB923bLOpb{EBqZk$xB%O3Fdz&N2_Sng-q!dqU<F{6MOgnBHVKW}5rGl7@c>FT
zwjgjA&;|e&+Yrf~s1D0D_n*q<_Thb+e4jmR`>=vwROOhfJ@3K7A<2KNiR6oOlM>8{
z3rwaIGRgczm7uRseXaf`(r0+>mD#4@>NB!Ag70Cke2MfKKist9atq6)4l!i!9&!M{
z>(esm<o~Vy{_rjH?VG2oxg$$vKH0&uvoaRm!<bv!Z|o4U-;e_%N0$mPbtjARVllFz
zbhK@{+yLK<@@8FnaZh{9^F3e7uIT!nub<k@%9M2J<FSqD#pl|?dX8M-Y2?Qf=;?im
z`FtX`1DTEG7bIv;ZW5jLz{V0ov#HHf+H5+-%9>3s3Y}nO(TAqW*SEB`v`Syd{;{UE
zH6yA_ZB^E@Ro1Rp(<!^Y%5<vA+99Wku_o6VsmkPvHJz~Iej+t7H8H(-uWUM{Iykx;
z1i7G%>lo~k`%eN|1)qLFHl5HiynqZYEyFWPhRuS<Y-}ksMs0=%&@On}nEK_CvyCu|
z#+c3PyVpoKxKmYfR-Vyv8h@u+PBj)7aN_2eZ0~pN8mO{U?%0x!;t!#{Bwa#D7cXlv
z#g-UL#OUs-lCCS1?Q_{smU8p5?_)$vZL;}PBwR!%LZ@=XJ}UBn1f@$G@0xS+5$V&Y
zNIbENkq6fQ1r7UzRhfIMO8QmKi)NwzHW=QN)|QIxKa?+|mUrl~iW1A4bh1u{KR>w$
z#O^JPjNNY!s<Mdkr;(pU?z4w^AMLjp5f6;ryXG%d<022n?tg4gv(Dpbe~0&uT+;6_
zw|UR{4799h!@sOsU%z@TP@rTqSAR)pN-ta-xcadZ9FxDd#l6ZOJY4E)9mQ|_0*X0k
z8Ys86G1Spx?k#>}kaY*L{F-~1^B@!w&VN7`;ryDE83TI3zY)rLu`yIH7)XU-Xso6S
zG!?qWw@7F4AwB&&={DfP;NN%wm!@%uHbsN`HQfV^MiaR&@AF|CD!=3Io?d%Z_OSg$
zvpItAVXt~l0>8-rU(YX8okwccf}Df}$;2{l6$VulHKd}@SVrF6**RBW8-{OT8;0*>
z8wQna+>^g>G3INqZKk8O4*VuXEN=$J?)Jo?tfn$Wnp#;*4;8c>?Gcx9qrof+?vDE!
z<Yc{kuQ>NK@W)DfIW<nLyiw}IF}sEZR{5NCHnJi5kjC-kBVc)?j@&|-!1Sbn^y2dc
z;B0Evo+ICqnO^A4Oy>wyHaJdUgK1!cM%YpR=d!`n#7o%Vm%eQ9Zwi<D(3cI?`?A45
zC>eHw4UTIm9Cs-jG!C-Cahwf;{ShCOnLGxJ4h-?M#tr}R%^){y+68|_l^X&Dal>(5
zZuo5|`dq&P3XLf?U4bc%_F;-xF|NQCPyVND@nOyu4OvA?%9{+t7Ihk1Ob1)MzRIFg
z+2UMKd1SJ_r@iNb00J7!x!*Pkylw)x<ZgvamW&34MJ9_qZIo4PujNeh*Wbl7O?t=i
zS@l&oHcIR>9JK(-YlpB;<=7;oa@V|XyiC$SOcM4l&G2qyH`YAFoH)-RIlD+#dp%vY
z6EA#&cwr;4!9&Cb-NY5ofKxWXec#Zuk}jpl*Yxkm*M!Vs)7!)(8;D(k-}*QEBiejB
zcqSeBkhc1;OHIDw?kIb_^5L-kS+Y3-{ng8dkCQ*xL*K`rMbihr$k=O|i1bTxAPZzu
zSPCm-8`*O(3$F~^Ufv`Tq!<6If$psr+Rq?;j6>&mP&YNgFEthPlwRD`uybm-AHq`W
zzuH>|GmP-fV7NktnZ6ljcr!S3b77L9%@0;cLhsN`WoqQSB5aLQoNj{1%?oaXRs(iG
zkh<Q7(~SX+XPl^H)f8T3htmxtg)(xw=^Em6bIEaFhq+5R(|blP&{x_!W_ijk`jv>Y
zj>0sBT_&bC`Q`A#zMBhzxl>LiWF;JH_C4|ommAGZ#~|AkHyv16Jl6B@(kTgulID?@
zj*FlBJ!m>pZtZ3slabE)zB)+cL9C%>CcDfKV!#e40LOsI?_HSzpA(Hw#I|M`2zI>>
z!K&*!H&4FnrPpEGH?uhc;p*u%j_kp2fnFi8=Ov_DlGAguGjJLNyMbH_ToV(LlXFsX
zb1!#?uvQ1c#_tFFMFKf@e5R3VJei3Vy#NVX{G_?n(9+h@Chg7s6>a7Cg}n22*GqNL
z9dIZm!(&HuJvsR4*u<J3<_tu4eQ>Q+_+X+{9PsHjD$jpv|8aMm-QNBiwm(lcN8q{o
z{(Fu3FXg|%KCEt-zzwp~^HVacjD4YPqF^85Y3PVdt=oS;*zFUo=t^iI$lz+5%WtL8
zm@<m7b2`73PKKSn(16K6c3eedS4_o<q1d6Dby86}cwO_YGG+(I8K>a99SR6V$dBZ=
z(kUDdA959oIpESGBRWl)p=bBh+{v6q47Bqa@O5VdiPbpcr+3C;(l~L_3WquA=}+is
zF+H`>({g%>Gk(GzU%F7}At!<M*UcI|<RlDtf2|-0yn1@LhUnpQ&HpJUD^Ht1jJ>Lj
z)r7&Z+Wj}FZmgqF4^ui(zsQo+Myc)L<hje+o?+8>4oC3K)wkzo)SjPfemOZ=mIPQO
z6%S{SU$fSvHENUAo?(*0{0-7kseqJFA^zkR+z)0TA6#Ewly198s+SH%ekPr>%KOi4
z-;6b4AgjPEANc0n_K->B5=<^{`}@yrZ@->$_Iwuk8D*qYd}Tt(LJ6A0VPJ=SDZ!UN
z<Z^oO`jh1jn;sMd-@~75BK6<jy@pv|mde;zt@|bqQUoR{5k;WmbYExPC`W7OMTIc_
zJhY7pedKcgWUoFcci8^P3WD#UPntsQ`>V#8U|{A(XN*Cz*0yPbZ6p8WK)7LdBsxq1
z#P|XF4o$gP>DxlJeOw%SU!(urVas#59D#K8^uLefxtliK%6w0ITy_-XGF@5U;E3m-
zPtv%B9}DILtyexEiS9NbLwHcI2~P`k0$(z@;1qp`yTJ$aoP(zeG+wx!r?f!m#VK-D
zN$Zjeg2^w)N5CQ#OaNr8=>@^lO_z#UIBTehS$&QJnj~d1Vor{ekMtCF$@}Gop2D-z
zo}R)W!88u8<ajiO9-UVnbxV7A`dMT^HMkVkd$|+_Pq~n2>?Atml5s<Yuf9Ry3%=O)
z0Y_nP^ijUq@mTu@OnqG58ep;&pK|FItQ})a<2>eo;<p9`FPv1-DSDcsQBuiSsi12W
zd|HCq-6VyELzk0&g>=KWq|dl=x+>oK;%cLJe5FXbzUk__w|ti{_(NLA?x%$eIv$Z!
z=KLElKl7z_O~0MX{R7|e()+Oe0~G}9>gjzp&FA;7?EeZcS7D?o7n0u^W_gcB&vOT7
zxhD2KrJcaIgr6zNMHjUt??1=|5CWgD!KX{q`On?cz4Be|u>IR}IfCyY-`z&~uXi`i
zW>+{%`Je01Kh_pbh-|q@IVmaT-1J2$!4mtU_F#yL9VWGxy$_W9X({QcX%>+&ug^G~
zeaxvT<O91*WF^%w_R(oma9&D!U0_`r>wyBE-k6u3Y)QjV8LHLsLtPT^^{FIFmpI6e
zW=I0w&PK$KW7o9eo}k?ExtuI9TUw{H_?3;Fh73Ou7K)3c&AI|V$JkpK)Bo9jlCgZu
z`r!M<KM=B8jn|CX9Q?%iEg^3sKFWWdv2Dzz;A7)Y<FqKgbtF6>J}5n_TjuwSeuID4
zh$W+E8t)nNcyQj>S>xFFB_U<>_6PL%$WOemk6p*^VyHEXmRbc6SiI1Mq(y2Has?o%
zTA*A3S}qYu$C0#1P5RLUHjXU=uA5X`N5s=3V7y!gTsNt>j)=%L4N27k<sw`>mk~+F
zk)+@{BI4{TO!va;sKi{g5<`-dO8ky;DFu~WN5mmXDtdv5`20}5_+#XLLYyX4<7jQH
z@F(^cW)?nYo$P)=6vhih0(>n$G&bu&0<2k2W2Ee{`N@1ma4*r94~#02+|_J-cd_2}
zp~t;}nV}JTvs~!6?i!2Y1<-u&(&;;K<g0V{UTG(Jf9_&ZC(X<;9f@bAly<yYt7EU$
z>H&<~SaD|e)mo9sUm%ZsM^e)I?jpmhSP;&2w)c9-UVjJKH3<(61=7kA?Rgu<llpV7
zXh;Lgu&0C8Qj^m}ujLb#S337D^NK&V6sQZd`VOz6m)0<l*D!8uQBP<4`Tx8gkWQnv
zK`)4NQu?TEIO5|qld6Vo*l78u!PFcusCaWMt+@r~WU=9Y3h)d77ESMmU*1CaZNNJK
z-;cQb1My>kF9BVEvw-th5F~&fz#k9-2nAdRm<}K_>Mejc0F1VcFxoa|0dRP?F&D5D
z@F1WN06T6Y+|L`=07?OHLvJhx(9zqCfGU6tcpUHq0QGM~{TpilF96=eGS!GL%`^^J
zgeJInHo?8K2`7u2#sF}Vc*6{^=_cBrHCd4IQ)F*~y}0Rj09bRIUI+XE@HyaL0HA5U
z1`uu$`h1u>h`5Z~b94Fj#Otq_JM8_9g5b*jn*XKm_f4nuZojr)0~a0K+|+4n+bx4@
z+eD%W^*j#Au|9_hH8D1fH&kt3F6~F(^seW*!`+YOas(Hyemzg6_U+W{)zIyvs|yjv
z;6AN^KOAfz7Vnnhj(*4IYg+~J4c*7B2Tx-j;lOZcXPrMd#a)i$WhXlWTI>8f>qcnt
zKL?zy8_}ukQ;sR)thC?4<r(k#Z5g&aqagSm>-Sk|zp&|s%h&45WcHET!fDA#Fy}(?
zVoA?PDaPRwZH-lv&~py0=eh@bj&FPMF%7QqvIi;$eYnhxvzRR_4ET4L1ECLj6At*z
zrT`tjBmgEDSzu7~>Q#1}>c&SK4ca+d=^{>5%l1I{Ums>92Ol1kg9CkdDcoSb|4Ung
zxGxInbxrVUIZH2h`M&(GzAx{h&wfC4BRVINbjuYs_`r_ne2SuV2&E03?&^HEa&mq{
zn-A7u&j$rT_tnpbQlf{VP01`UGv7x$^KH`I5C@1$JtP8rKC)p=&#^2>$WTNs9b@~n
zXOOmrJcH-M8jX5Nnc!8g@fC5Gz}DIg@xscv*}HXc8tN%A%rWWnAB%*l?Z#e@wlvcU
zt>{uQU9m{R=g3o{=XzDu56X)cu0V`|XOSzAhyYxHG!2}A4b<GgzaF9EXUbrVmOhwc
z6`Tnc;e)%ZqVs;NPCvE?!X-lq`q%h(UNZ5wKWpQempoklrXbK={dkU`@odxho393&
zu>!51N6{?Rb|VK)en)%wcHvLn_6&Q!k;f5Sy!!S`p!OWmMD@I!bPE^t(c|A}t(i2)
zbD+F+6zZ|7F8d(9&QImQmhWgEUvK~5ZQroh+dPh-_v+g>gWA`iwJ#?nAsOZda|)ah
zM`(*MZ!}LutG$cxZG)}mO;$hRsw_H+xJD{%>I_n8E9pP=c7?JY<?+u4dHGM?u)jZ~
zAow2q=W=?5ekdm)i8j+Kv=R29*P@FDzVbE#d9>fx|I|YNpWN?}A6SRg(w24uW7pwG
zDE*@OwJ4W8%*M|DclOH{@fBs|16-fu{H-+PlLGxn8RvCjo5iEvFVyDGRN^parDjIF
zA&dZG3TH<+1=_A*u>c=eMMEc;NzkP#z_WtL0tlaapk}Fvlh6#ud#D^4a0H#iB7ieD
zAtFh4EpP$@o(*aRev1quVNkd7N}Nh$M|`7$q(HS86i~mxB4fZ)OGd;5zi>Ro>f|f9
zOz>k&RE>HniB<Rs-0K&a|F8RfwEE@i*bTFnpyDfEV_TqFIQ#-LEi<25)G)7REZbc9
zk9AS(jQ1<r0!Dl2=Z2$@G8%o39vu7{)=(-~s8WGOB?||s1S3VIy!lluO8g4K1Al<g
zF=a>GFOc3tp#-i5eg=zv07lFAV+n77rpDvIG#!xUq=b?4IfokvY8p=znPHBYB;r$Z
z40%ZfHwnIzlNG9?LtqNkAzyZS#9j$LR8%J09Pv*HA84R(PC~?F-8E`BJK|Oyd4Z!>
zh8T8k)sb$3TYv|Z*Nb%`3nr@f)k`Tf3Y{SON6{&HsWvY;Vxiw;U<cI>a`YlU9UF~$
z<mE(E_}z%7!};CI;)~5}>djOpjajdU76QMu{5saL^e5~o^qS8nc<zUe{aSVIs-Gb^
zBuH#B-k)xXI4j@?E}6YickNuA(tk+9_zq1|4(bh^$w?7+>#hS1JR^Fb53}5jUNQoI
zZhFLG-2^<Na7M&tT^PdXi9zKZ?<jiH;FfHppM;NHE7UYZW{kswN$6#-I8caglo(RH
z3n=ecyyO4b-`J-n&1XN__#cpgOBsfh{gmB^&DmSI?D;wOWxl~4k7kj3(A$ZL5tvK(
zA)J&H5k+DH4`)Ptjy_YuIT8H~{L|N{qs`b<Ys4X8q>?W!BjO7IR-146yw?{XrZAd`
z^qB)bYcJU$XfxTz6*^qfu`yJiY*WO|66rQUJ(^ea&5{I-DJXK#>+uof52rkuThLy(
zJ_b?w1oJ-;4CA=6BLrQDQs>;vh~Mh2N0{p3qXFjhhH|;N5hMNR$PBoKx}oJu1>v#g
zM#T9=;2G-RBT6sCx<NJl-}&3dtgq7h<F38yHg*I1L*fdyr9AuR_ri!;h~%guTpoWL
zZAeOu_yF9Cx54N0rXOIuuT$6DOZh)anGz%B30N_yS7<cwt+sh!)03!IQj;P!3jTP8
zQJ{5z=J`fEq}4YyJ>nUzI7c`mBO*}58GI^}Wr<jdLtT6nR9?c%aR!5TAdODq4)W{7
zh;RumAAB@ZBOZ~)A`E^pxJ8`|raYGO<Uy~TB+#(rYmwOu_5%iciRZq;lfhR|`^)(X
aYMYlCQRoM`ir$`=9Z}>r1>yg*e*Xh>)L^y%

literal 0
HcmV?d00001

diff --git a/16/scrasm/80X86.ASC b/16/scrasm/80X86.ASC
new file mode 100644
index 00000000..e16af972
--- /dev/null
+++ b/16/scrasm/80X86.ASC
@@ -0,0 +1,164 @@
+_80x86 OPTIMIZATION_
+by Michael Abrash
+
+
+[LISTING ONE]
+
+; Copies one string to another string, converting all characters to
+; uppercase in the process, using a loop containing LODSB and STOSB.
+; Adapted from Zen of Assembly Language, by Michael Abrash; not a
+; standalone program, but designed to be used with the Zen timer from
+; that book via the Zen timer's PZTIME.BAT batch file: ZTimerOn starts
+; the clock, ZTimerOff stops it, and the test-bed program linked in by
+; PZTIME.BAT starts the program, reports the results, and ends.
+
+	jmp	Skip		;skip over data in CS and subroutine
+
+SourceString	label	word		;sample string to copy
+	db	'This space intentionally left not blank',0
+DestString	db	100 dup (?)	;destination for copy
+
+; Copies one zero-terminated string to another string,
+; converting all characters to uppercase.
+; Input: DS:SI = start of source string; DS:DI = start of destination buffer
+; Output: none
+; Registers altered: AX, BX, SI, DI, ES
+; Direction flag cleared
+
+CopyStringUpper:
+	mov	ax,ds
+	mov	es,ax	;for STOS
+	mov	bl,'a'	;set up for fast register-register
+	mov	bh,'z'	; comparisons
+	cld
+StringUpperLoop:
+	lodsb		;get next character and point to following character
+	cmp	al,bl	;below 'a'?
+	jb	IsUpper	;yes, not lowercase
+	cmp	al,bh	;above 'z'?
+	ja	IsUpper	;yes, not lowercase
+	and	al,not 20h ;is lowercase-make uppercase
+IsUpper:
+	stosb		;put character into new string and point to 
+                        ; following location
+	and	al,al	;is this the zero that marks end of the string?
+	jnz	StringUpperLoop ;no, do the next character
+	ret
+
+; Calls CopyStringUpper to copy & convert SourceString->DestString.
+Skip:
+	call	ZTimerOn		;start timing
+	mov	si,offset SourceString	;point SI to the string to copy from
+	mov	di,offset DestString	;point DI to the string to copy to
+	call	CopyStringUpper		;copy & convert to uppercase
+	call	ZTimerOff		;stop timing
+
+
+[LISTING TWO]
+
+; Copies one string to another string, converting all characters to
+; uppercase in the process, using no string instructions.
+; Not a standalone program, but designed to be used with the Zen
+; timer, as described in Listing 1.
+
+	jmp	Skip		;skip over data in CS and subroutine
+
+SourceString	label	word		;sample string to copy
+	db	'This space intentionally left not blank',0
+DestString	db	100 dup (?)	;destination for copy
+
+; Copies one zero-terminated string to another string,
+; converting all characters to uppercase. 
+; Input: DS:SI = start of source string; DS:DI = start of destination string
+; Output: none
+; Registers altered: AL, BX, SI, DI
+
+CopyStringUpper:
+	mov	bl,'a'	;set up for fast register-register
+	mov	bh,'z'	; comparisons
+StringUpperLoop:
+	mov	al,[si]	;get the next character and
+	inc	si	; point to the following character
+	cmp	al,bl	;below 'a'?
+	jb	IsUpper	;yes, not lowercase
+	cmp	al,bh	;above 'z'?
+	ja	IsUpper	;yes, not lowercase
+	and	al,not 20h ;is lowercase-make uppercase
+IsUpper:
+	mov	[di],al	;put the character into the new string and
+	inc	di	; point to the following location
+	and	al,al	;is this the zero that marks the end of the string?
+	jnz	StringUpperLoop ;no, do the next character
+	ret
+
+; Calls CopyStringUpper to copy & convert SourceString->DestString.
+Skip:
+	call	ZTimerOn
+	mov	si,offset SourceString	;point SI to the string to copy from
+	mov	di,offset DestString	;point DI to the string to copy to
+	call	CopyStringUpper		;copy & convert to uppercase
+	call	ZTimerOff
+
+
+[LISTING THREE]
+
+; Clears a buffer using MOV/ADD in a loop.
+; Not a standalone program, but designed to be used with the Zen
+; timer, as described in Listing 1.
+
+	mov	dx,2		;repeat the test code twice, to make
+				; sure it's in the cache (if there is one)
+	mov	bx,dx		;distance from the start of one word
+				; to the start of the next
+	sub	ax,ax		;set buffer to zeroes
+TestTwiceLoop:
+	mov	cx,1024		;clear 1024 words starting at address
+	mov	di,8000h	; DS:8000h (this is just unused memory
+				; past the end of the program)
+	call	ZTimerOn	;start timing (resets timer to 0)
+StoreLoop:
+	mov	[di],ax		;clear the current word
+	add	di,bx		;point to the next word
+	dec	cx		;count off words to clear until none
+	jnz	StoreLoop	; remain
+	call	ZTimerOff	;stop timing
+	dec	dx		;count off passes through test code
+	jz	StoreDone	;that was the second pass; we're done
+	jmp	TestTwiceLoop	;that was first pass; do second pass with all 
+                                ; instructions and data in the cache
+StoreDone:
+
+
+[LISTING FOUR]
+
+; Clears a buffer using MOV/ADD in an unrolled loop.
+; Not a standalone program, but designed to be used with the Zen
+; timer, as described in Listing 1.
+
+	mov	dx,2		;repeat the test code twice, to make
+				; sure it's in the cache (if there is one)
+	mov	bx,dx		;distance from the start of one word
+				; to the start of the next
+	sub	ax,ax		;set buffer to zeroes
+TestTwiceLoop:
+	mov	si,1024		;clear 1024 words starting at address
+	mov	di,8000h	; DS:8000h (this is just unused memory
+				; past the end of the program)
+	call	ZTimerOn	;start timing (resets timer to 0)
+	mov	cl,4		;divide the count of words to clear by
+	shr	si,cl		; 16, because we'll clear 16 words
+				; each time through the loop
+StoreLoop:
+	REPT	16		;clear 16 words in a row without looping
+	mov	[di],ax		;clear the current word
+	add	di,bx		;point to the next word
+	ENDM
+	dec	si		;count off blocks of 16 words to clear
+	jnz	StoreLoop	; until none remain
+	call	ZTimerOff	;stop timing
+	dec	dx		;count off passes through test code
+	jz	StoreDone	;that was the second pass; we're done
+	jmp	TestTwiceLoop	;that was the first pass; do the second pass 
+                                ; with all instructions and data in the cache
+StoreDone:
+
diff --git a/16/scrasm/80X86.TXT b/16/scrasm/80X86.TXT
new file mode 100644
index 00000000..afba3707
--- /dev/null
+++ b/16/scrasm/80X86.TXT
@@ -0,0 +1,494 @@
+Journal:   Dr. Dobb's Journal  March 1991 v16 n3 p16(8)
+-----------------------------------------------------------------------------
+Title:     80x86 optimization: aim down the middle and pray. (80x86 family of
+           microprocessors) (tutorial)
+Author:    Abrash, Michael.
+AttFile:    Program:  80X86.ASC  Source code listing.
+
+Summary:   Optimizing code for 8088, 80286, 80386 and 80486 microprocessors
+           is difficult because the chips use significantly different memory
+           architectures and instruction execution times.  Code cannot be
+           optimized for the 80x86 family; rather, code must be designed to
+           produce good performance on a range of systems or optimized for
+           particular combinations of processors and memory.  Programmers
+           must avoid the unusual instructions supported by the 8088, which
+           have lost their performance edge in subsequent chips.  String
+           instructions should be used but not relied upon.  Registers should
+           be used rather than memory operations.  Branching is also slow for
+           all four processors.  Memory accesses should be aligned to improve
+           performance.  Generally, optimizing an 80486 requires exactly the
+           opposite steps as optimizing an 8088.
+-----------------------------------------------------------------------------
+Descriptors..
+Company:   Intel Corp. (Products).
+Ticker:    INTC.
+Product:   Intel 80286 (Microprocessor) (Programming)
+           Intel 80386 (Microprocessor) (Programming)
+           Intel 80486 (Microprocessor) (Programming)
+           Intel 8088 (Microprocessor) (Programming).
+Topic:     Microprocessors
+           Optimization
+           Programming
+           Tutorial
+           Assembly Language
+           Guidelines
+           Type-In Programs
+           Microcode
+           Processor Architecture.
+Feature:   illustration
+           graph.
+Caption:   Official and actual cycles per binary-to-hex ASCII conversion.
+           (graph)
+           Actual performance in microseconds of two solutions to a problem.
+           (graph)
+           Actual performance of three clearing approaches across the 80x86
+           family. (graph)
+
+-----------------------------------------------------------------------------
+Full Text:
+
+Optimization
+
+Picture this: You're an archer aiming at a target 100 feet away.  A strong
+wind comes up and pushes each arrow to the left as it flies.  Naturally, you
+compensate by aiming farther to the right.  That's what it's like optimizing
+for the 8088; once you learn to compensate for the strong but steady effects
+of the prefetch queue and the 8-bit bus, you can continue merrily on your
+programming way.
+
+Now the wind starts gusting unpredictably.  There's no way to compensate, so
+you just aim for the bull's-eye and hope for the best.  That's what it's like
+writing code for good performance across the entire 80x86 family, or even for
+the 286/386SX/386 heart of today's market.  You just aim down the middle and
+pray.
+
+The New World of the 80x86
+
+In the beginning, the 8088 was king, and that was good.  The optimization
+rules weren't obvious, but once you learned them, you could count on them
+serving you well on every computer out there.
+
+Not so these days.  There are four major processor types--8088, 80286, 80386,
+and 80486--with a bewildering array of memory architectures: cached (in
+several forms), page mode, static-column RAM, interleaved, and, of course,
+the 386SX, with its half-pint memory interface.  The processors offer wildly
+differing instruction execution times, and memory architectures warp those
+times further by affecting the speed of instruction fetching and access to
+memory operands.  Because actual performance is a complex interaction of
+instruction characteristics, instruction execution times, and memory access
+speed, the myriad processor-memory combinations out there make "exact
+performance" a meaningless term.  A specific instruction sequence may run at
+a certain speed on a certain processor in a certain system, but that often
+says little about the performance of the same instructions on a different
+processor, or even on the same processor with a different memory system.  The
+result: Precise optimization for the general PC market is a thing of the
+past.  (We're talking about optimizing for speed here; optimizing for size is
+the same for all processors so long as you stick to 8088-compatible code.)
+
+So there is no way to optimize performance ideally across the 80x86 family.
+An optimization that suits one processor beautifully is often a dog on
+another.  Any 8088 programmer would instinctively replace:
+
+DEC  CX JNZ  LOOPTOP
+
+with:
+
+LOOP  LOOPTOP
+
+because LOOP is significantly faster on the 8088.  LOOP is also faster on the
+286.  On the 386, however, LOOP is actually two cycles slower than DEC/JNZ.
+The pendulum swings still further on the 486, where LOOP is about twice as
+slow as DEC/JNZ--and, mind you, we're talking about what was originally
+perhaps the most obvious optimization in the entire 80x86 instruction set.
+
+In short, there is no such thing as code that's truly optimized for the
+80x86.  Instead, code is either optimized for specific processor-memory
+combinations, or aimed down the middle, designed to produce good performance
+across a range of systems.  Optimizing for the 80x86 family by aiming down
+the middle is quite different from optimizing for the 8088, but many PC
+programmers are inappropriately still applying the optimization lore they've
+learned over the years on the PC (or AT).  The world has changed, and many of
+those old assumptions and tricks don't hold true anymore.
+
+You will not love the new world of 80x86 optimization, which is less precise
+and offers fewer clever tricks than optimizing for the 8088 alone.  Still,
+isn't it better to understand the forces affecting your code's performance
+out in the real world than to optimize for a single processor and hope for
+the best?
+
+Better, yes.  As much fun, no.  Optimizing for the 8088 was just about as
+good as it gets.  So it goes.
+
+Optimization Rules for a New World
+
+So, how do you go about writing fast code nowadays?  One way is to write
+different versions of critical code for various processors and memory access
+speeds, selecting the best version at runtime.  That's a great solution, but
+it requires an awful lot of knowledge and work.
+
+An alternative is to optimize for one particular processor and settle for
+whatever performance you get on the others.  This might make sense when the
+8088 is the target processor because it certainly needs the optimization more
+than any other processor.  However, 8088 optimization works poorly at the
+upper end of the 80x86 family.
+
+Nowadays, though, most of us want to optimize for the 286 and 386 systems
+that dominate the market, or across all 80x86 processors, and that's a tough
+nut to crack.  The 286 and 386 come in many configurations, and you can be
+sure, for example, that a 386SX, an interleaved 386, and a cached 386 have
+markedly different performance characteristics.  There are, alas, no hard and
+fast optimization rules that apply across all these environments.
+
+My own approach to 80x86 optimization has been to develop a set of general
+rules that serve reasonably well throughout the 80x86 line, especially the
+286 and 386, and to select a specific processor (in my case a cached 386, for
+which cycle times tend to be accurate) to serve as the tiebreaker when
+optimization details vary from one processor to another.  (Naturally, it's
+only worth bothering with these optimizations in critical code.)  The rules
+I've developed are:
+
+* Avoid accessing memory operands; use the registers to the max.
+
+* Don't branch.
+
+* Use string instructions, but don't go much out of your way to do so.
+
+* Keep memory accesses to a minimum by avoiding memory operands and keeping
+instructions short.
+
+* Align memory accesses.
+
+* Forget about many of those clever 8088 optimizations, using oddball
+instructions such as DAA and XLAT, that you spent years learning.
+
+Next I'll discuss each of these rules in turn in the context of
+8088-compatible real mode, which is still the focus of the 80x86 world.
+Later, I'll touch on protected mode.
+
+Let's start by looking at the last--and most surprising--rule.
+
+Kiss Those Tricks Goodbye
+
+To skilled assembly language programmers, the 8088 is perhaps the most
+wonderful processor ever created, largely because the instruction set is
+packed with odd instructions that are worthless to compilers but can work
+miracles in the hands of clever assembly programmers.  Unfortunately, each
+new generation of the 80x86 has rendered those odd instructions and marvelous
+tricks less desirable.  As the execution time for the commonly used
+instruction ADD BX, 4 has gone down from four cycles (8088) to three cycles
+(286) to two cycles (386) to one cycle (486), the time for the less
+frequently used instruction CBW has gone from two cycles (8088 and 286) up to
+three cycles (386 and 486)!
+
+Consider this ancient optimization for converting a binary digit to hex
+ASCII:
+
+ADD  AL,90H DAA ADC  AL,40H DAA
+
+Now consider the standard alternative:
+
+ADD  AL,'0' CMP  AL,'9' JBE  HaveAscii ADD  AL,'A'-('9'+1) HaveAscii:
+
+As Figure 1 indicates, the standard code should be slower on an 8088 or 286,
+but faster on a 386 or a 486--and real-world tests confirm those results, as
+shown in Figure 2.  (All "actual performance" timings in this article were
+performed with the Zen timer from Zen of Assembly Language, see "References"
+for details.  The systems used for the tests were: 8088, standard 4.77 MHz PC
+XT; 80286, standard one-wait-state, 8 MHz PC AT; 386SX, 16 MHz noncached;
+80386, 20 MHz externally cached with all instructions and data in external
+cache for all tests except Listings One and Two; 80486, 25 MHz internally
+cached, with all instructions and data in internal cache for all tests except
+Listings One and Two.)
+
+In other words, this nifty, time-tested optimization is an anti-optimization
+on the 386 and 486.
+
+Why is this?  On the 386, DAA--a rarely used instruction--takes four cycles,
+and on the 486 it takes two cycles, in both cases twice as long as the more
+common instructions CMP and ADD; in contrast, on the 8088 all three
+instructions are equally fast at four cycles.  Also, the instruction-fetching
+advantage that the 1-byte DAA provides on the 8088 means nothing on a cached
+386.
+
+Nor is this an isolated example.  Most oddball instructions, from AAA to
+XCHG, have failed to keep pace with the core instructions--ADC, ADD, AND,
+CALL, CMP, DEC, INC, Jcc, JMP, LEA, MOV, OR, POP, PUSH, RET, SBB, SUB, TEST,
+and XOR--during the evolution from 8088 to 486.  As we saw earlier, even LOOP
+lags behind on the 386 and 486.  Check your favorite tricks for yourself;
+they might or might not hold up on the 386, but will most likely be
+liabilities on the 486.  Sorry, but I just report the news, and the news is:
+Kiss most of those tricks goodbye as the 386 and 486 come to dominate the
+market.  (This means that hand-optimization in assembly language yields less
+of a performance boost nowadays than it did when the 8088 was king; the
+improvement is certainly significant, but rarely in the 200-500 percent range
+anymore.  Sic transit gloria mundi.)  Most startling of all, string
+instructions lose much of their allure as we move away from the 8088, hitting
+bottom on the 486.
+
+The 486: All the Rules Change
+
+The 486 represents a fundamental break with 8088-style optimization.
+Virtually all the old rules fail on the 486, where, incredibly, a move to or
+from memory often takes just one cycle, but exchanging two registers takes
+three cycles.  The nonbranching core instructions mentioned earlier take only
+one cycle on the 486 when operating on registers; MOV can, under most
+conditions, access memory in one cycle; and CALL and JMP take only three
+cycles, given a cache hit.  However, noncore instructions take considerably
+longer.  XLAT takes four cycles; even STC and CLC take two cycles each.  The
+486's highly asymmetric execution times heavily favor core instructions and
+defeat most pre-486 optimizations.
+
+Core instructions do have a weakness on the 486.  While 486 MOVs involving
+memory are remarkably fast, accessing memory for an operand to OR, ADD, or
+the like costs cycles.  Even with the 8K internal cache, memory is not as
+fast as registers, except when MOV is used (and sometimes not even then), so
+registers are still preferred operands.  (AND [BX],1 is fast, at only three
+cycles, but AND BX,1 takes only one cycle--three times as fast.)
+
+OUT should be avoided whenever possible on the 486, and likewise for IN.  OUT
+takes anywhere from 10 to 31 cycles, depending on processor mode and
+privileges, more than an order of magnitude slower than MOV.  The lousy
+performance of OUT -- true on the 386 as well -- has important implications
+for graphics applications.
+
+String instructions are so slow on the 486 that you should check cycle times
+before using any string instruction other than the always superior REP MOV's.
+For example, LODSB takes five cycles on the 486, but MOV AL,[SI]/INC SI takes
+only two cycles; likewise for STOSB and MOV [DI],AL/INC DI.  Listing One
+(page 73) uses LODSB/STOSB to copy a string, converting lowercase to
+uppercase while copying; Listing Two (page 73) uses MOV/INC instead.  Figure
+3 summarizes the performance of the two routines on a variety of processors;
+note the diminishing effectiveness of string instructions on the newer
+processors.  Think long and hard before using string instructions other than
+REP MOVS on the 486.
+
+Optimization for the 486 is really a whole new ball game.  When optimizing
+across the 80x86 family, the 486 will generally be the least of your worries
+because it is so much faster than the rest of the family; anything that runs
+adequately on any other processor will look terrific on the 486.  Still, the
+future surely holds millions of 486s, so it wouldn't hurt to keep one eye on
+the 486 as you optimize.
+
+String Instructions: Fading Stars
+
+On the 8088, string instructions are so far superior to other instructions
+that it's worth going to great lengths to use them, but they lose much of
+that status on newer processors.  One of the best things about string
+instructions on the 8088 is that they require little instruction fetching,
+because they're 1-byte instructions and because of the REP prefix; however,
+instruction fetching is less of a bottleneck on newer processors.  String
+instructions also have superior cycle times on the 8088, but that advantage
+fades on the 286 and 386 as well.
+
+On the 286, string instructions (when they do exactly what you need) are
+still clearly better than the alternatives.  On the 386, however, some string
+instructions are, even under ideal circumstances, the best choice only by a
+whisker, if at all.  For example, since Day One, clearing a buffer has been
+done with REP STOS.  That's certainly faster than the looping MOV/ADD
+approach shown in Listing Three (page 73), but on the 386 and 486 it's no
+faster than the unrolled loop MOV/ADD approach of Listing Four (page 73), as
+shown in Figure 4.  (Actually, in my tests REP STOS was a fraction of a cycle
+slower on the 386, and fractionally faster on the 486.)  REP STOS is much
+easier to code and more compact, so it's still the approach of choice for
+buffer clearing--but it's not necessarily fastest on a 486 or fast-memory
+386.  This again demonstrates just how unreliable the old optimization rules
+are on the newer processors.
+
+The point is not that you shouldn't use string instructions on the 386.  REP
+MOVs is the best way to move data, and the other string instructions are
+compact and usually faster, especially on uncached systems.  However, on the
+386 it's no longer worth going to the trouble of juggling registers and
+reorganizing data structures to use string instructions.  Furthermore, when
+you truly need maximum performance on the 386, check out nonstring
+instructions in unrolled loops.  It goes against every lesson learned in a
+decade of 8088 programming, but avoiding string instructions sometimes pays
+on the 386.
+
+The Siren Song of Memory Accesses
+
+Finally, here's a rule that's constant from the 8088 to the 486: Use the
+registers.  Avoid memory.
+
+Don't be fooled by the much faster memory access times of the 286 and 386.
+The effective address calculation time of the 8088 is mostly gone, so MOV
+AX,[BX] takes only five cycles on the 286, and ADD [SI],DX takes only seven
+on the 386.  That's so much faster than the 17 and 29 cycles, respectively,
+that they take on the 8088 that you might start thinking that memory is
+pretty much interchangeable with registers.
+
+Think again.  MOV AX,BX is still more than twice as fast as MOV AX,[BX] on
+the 286, and ADD SI,DX is more than three times as fast as ADD [SI],DX on the
+386.  Memory operands can also reduce performance by slowing instruction
+fetching.  Memory is fast on the 286 and 386.  Registers are faster.  Use
+them as heavily as possible.
+
+Don't Branch
+
+Here's another rule that stays the same across the 80x86 family: Don't
+branch.  Branching suffers on the 8088 from lengthy cycle counts and emptying
+the prefetch queue.  Emptying the prefetch queue is a lesser but nonetheless
+real problem in the post-8088 world, and the cycle counts of branches are
+still killers.  As Figure 4 indicates, it pays to eliminate branches by
+unrolling loops or using repeated string instructions.
+
+Modern-Day Instruction Fetching
+
+Instruction fetching is the bugbear of 8088 performance; the 8088 simply
+can't fetch instruction bytes as quickly as it can execute them, thanks to
+its undersized bus.  Minimizing all memory accesses, including instruction
+fetches, is paramount on the 8088.
+
+Instruction fetching is less of a problem nowadays.  Figure 5 shows the
+maximum rates at which various processors can fetch instruction bytes;
+clearly, matters have improved considerably since the 8088, although
+instructions also execute in fewer cycles on the newer processors.  Fetching
+problems can occur on any 80x86 processor, even the 486, but the only
+processors other than the 8088 that face major instruction fetching problems
+are the one-wait-state 286 and the 386SX, although uncached 386s may also
+outrun memory.  However, the problems here are different from and less
+serious than with the 8088.
+
+Consider: An 8088 executes a register ADD in three cycles, but requires eight
+cycles to fetch that instruction, a fetch/execute ratio of 2.67.  A
+one-wait-state 286 requires three cycles to fetch a register ADD and executes
+it in two cycles, a ratio of 1.5.  A 386SX can fetch a register ADD in two
+cycles, matching the execution time nicely, and a cached 386 can fetch two
+register ADDs in the two cycles it takes to execute just one.  For
+register-only code--the sort of code critical loops should contain--the 386
+generally runs flat out, and the 286 and 386SX usually (not always, but
+usually) outrun memory by only a little at worst.  Greater fetching problems
+can arise when working with large instructions or instruction sequences that
+access memory nonstop, but those are uncommon in critical code.  This is a
+welcome change from the 8088, where small, register-only instructions tend to
+suffer most from inadequate instruction fetching.
+
+Also, uncached 386 systems often use memory architectures that provide
+zero-wait-state performance when memory is accessed sequentially.  In
+register-only code, instruction fetches are the only memory accesses, so
+fetching proceeds at full speed when the registers are used heavily.
+
+So, is instruction fetching a problem in the post-8088 world?  Should
+instructions be kept short?
+
+Yes.  Smaller instructions can help considerably on the one-wait-state 286
+and on the 386SX.  Not as much as on the 8088, but it's still worth the
+trouble.  Even a cached 386 can suffer from fetching problems, although
+that's fairly uncommon.  For example, when several MOV WORD PTR [MemVar],0
+instructions are executed in a row, as might happen when initializing memory
+variables, performance tends to fall far below rated speed, as shown in
+Figure 6.  The particular problem with MOV WORD PTR [MemVar],0 is that it
+executes in just two (386) or three (286) cycles, yet has both an addressing
+displacement field and a constant field.  This eats up memory bandwidth by
+requiring more instruction fetching.  It also accesses memory, eating up
+still more bandwidth.  We'll see this again, and worse, when we discuss
+protected mode.
+
+Generally, though, post-8088 processors with fast memory systems and
+full-width buses run most instructions at pretty near their official cycle
+times; for these systems, optimization consists mostly of counting cycles.
+Slower memory or constricted buses (as in the 386SX) require that memory
+accesses (both instruction fetches and operand accesses) be minimized as
+well.  Fortunately, the same sort of code--register only--meets both
+requirements.
+
+Use the registers.  Avoid constants.  Avoid displacements.  Don't branch.
+That's the big picture.  Don't sweat the details.
+
+Alignment: The Easy Optimization
+
+The 286, 386SX, and 386 take twice as long to access memory words at odd
+addresses as at even addresses.  The 386 takes twice as long to access memory
+dwords at addresses that aren't multiples of four as those that are.  You
+should use ALIGN 2 to word align all word-sized data, and ALIGN 4 to dword
+align all data that's accessed as a dword operand, as in:
+
+ALIGN  4 MemVar  dd  ? : MOV EAX,[MemVar]
+
+Alignment also applies to code; you may want to word or dword align the
+starts of procedures, labels that can only be reached by branching, and the
+tops of loops.  (Code alignment matters only at branch targets, because only
+the first instruction fetch after a branch can suffer from nonalignment.)
+Dword alignment of code is optimal, and will help on the 386 even in real
+mode, but word alignment will produce nearly as much improvement as dword
+alignment without wasting nearly as many bytes.
+
+Alignment improves performance on many 80x86 systems without hindering it on
+any.  Recommended.
+
+Protected Mode
+
+There are two sorts of protected mode, 16-bit and 32-bit.  The primary
+optimization characteristic of 16-bit protected mode (OS/2 1.X, Rational DOS
+Extender) is that it takes an ungodly long time to load a segment register
+(for example, MOV ES,AX takes 17 cycles on a 286) so load segment registers
+as infrequently as possible in 16-bit protected mode.
+
+Optimizing for 32-bit protected mode (OS/2 2.0, SCO Unix, Phar Lap DOS
+Extender) is another matter entirely.  Typically, no segment loads are needed
+because of the flat address space.  However, 32-bit protected mode code can
+be bulky, and that can slow instruction fetching.  Constants and addressing
+displacements can be as large as 4 bytes each, and an extra byte, the SIB
+byte, is required whenever two 32-bit registers are used to address an
+operand or scaled addressing is used.  So, for example, MOV DWORD PTR
+[MemVar],0 is a 10-byte instruction in 32-bit protected mode.  The
+instruction is supposed to execute in two cycles, but even a 386 needs four
+to six cycles to fetch it, plus another two cycles to access memory; a few
+such instructions in a row can empty the prefetch queue and slow performance
+considerably.  The slowdown occurs more quickly and is more acute on a 386SX,
+which needs 14 cycles to perform the memory accesses for this nominally
+2-cycle instruction.
+
+Code can get even larger when 32-bit instructions are executed in 16-bit
+segments, adding prefix bytes.  (Avoid prefix bytes if you can; they increase
+instruction size and can cost cycles.)  Figure 7 shows actual versus nominal
+cycle times of multiple MOV DWORD PTR [EBX*4+MemVar],0 instructions running
+in a 16-bit segment.  Although cache type (write-back, write-through) and
+main-memory write time also affect the performance of stores to memory, there
+is clearly a significant penalty for using several large (in this case,
+13-byte) instructions in a row.
+
+Fortunately, this is a worst case, easily avoided by keeping constants and
+displacements out of critical loops.  For example, you should replace:
+
+ADDLOOP: MOV  DWORD PTR BaseTable[EDX+EBX],0 ADD  EBX,4 DEC  ECX JNZ  ADDLOOP
+
+with:
+
+LEA  EBX,BaseTable[EDX+EBX] SUB  EAX,EAX ADDLOOP: MOV  [EBX],EAX ADD  EBX,4
+DEC  ECX JNZ  ADDLOOP
+
+Better yet, use REP STOSD or unroll the loop!
+
+Happily, register-only instructions are no larger in 32-bit protected mode
+than otherwise and run at or near their rated speed in 32-bit protected mode
+on all processors.  All in all, in protected mode it's more important than
+ever to avoid large constants and displacements and to use the registers as
+much as possible.
+
+Conclusion
+
+Optimization across the 80x86 family isn't as precise as 8088 optimization,
+and it's a lot less fun, with fewer nifty tricks and less spectacular
+speed-ups.  Still, familiarity with the basix 80x86 optimization rules can
+give you a decided advantage over programmers still laboring under the
+delusion that the 286, 386, and 486 are merely faster 8088s.
+
+References
+
+Abrash, Michael.  Zen of Assembly Language.  Glenview, Ill.: Scott, Foresman,
+1990.
+
+Barrenechea, Mark.  "Peak Performance: On to the 486."  Programmer's Journal,
+(November-December 1990).
+
+Paterson, Tim.  "Assembly Language Tricks of the Trade."  Dr. Dobb's Journal
+(March 1990).
+
+Turbo Assembler Quick Reference Guide.  Borland International, 1990.
+
+i486 Microprocessor Programmer's Reference Manual.  Intel Corporation, 1989.
+
+80386 Programmer's Reference Manual.  Intel Corporation, 1986.
+
+Microsystems Components Handbook: Microprocessors Volume I.  Intel
+Corporation, 1985.
diff --git a/16/scrasm/CONSTANT.INC b/16/scrasm/CONSTANT.INC
new file mode 100644
index 00000000..02ce404b
--- /dev/null
+++ b/16/scrasm/CONSTANT.INC
@@ -0,0 +1,127 @@
+PEL_READ_REG    EQU     03C7h   ;Color register, read address
+PEL_WRITE_REG   EQU     03C8h   ;Color register, write address
+PEL_DATA_REG    EQU     03C9h   ;Color register, data port
+SC_INDEX        equ     03C4h   ;Sequence Controller Index
+CRTC_INDEX      equ     03D4h   ;CRT Controller Index
+MISC_OUTPUT     equ     03C2h   ;Miscellaneous Output register
+SCREEN_SEG      equ     0a000h  ;segment of display memory in mode X
+INPUT_STATUS_1  equ     03DAh   ;Input Status 1 register
+ATC_INDEX       equ     03C0h   ;Attribute Controller
+START_ADDRESS_HIGH equ  0Ch     ;bitmap start address high byte
+START_ADDRESS_LOW equ   0Dh     ;bitmap start address low byte
+GC_INDEX        EQU     03CEh
+BIT_MASK        EQU     08h
+MAP_MASK        EQU     02h
+
+ALL_COPY_BITS   EQU     00000h+BIT_MASK
+ALL_DRAW_BITS   EQU     0FF00h+BIT_MASK
+
+SQUARE_WIDTH    EQU     16
+SQUARE_HEIGHT   EQU     16
+SCREEN_WIDTH    EQU     320
+SCREEN_HEIGHT   EQU     240
+VIRTUAL_WIDTH   EQU     352
+VIRTUAL_HEIGHT  EQU     240
+
+PAGE_0          EQU     0
+PAGE_1          EQU     05540h  ;05470h  ;5540h
+PAGE_2          EQU     0AA80h  ;0A8E0h  ;AA80h
+
+SCROLL_SPEED    EQU     1               ; Don't let it go above 8!
+MAGIC_NUM       EQU     100
+
+CPU8086         EQU     0
+CPU80286        EQU     1
+CPU80386        EQU     2
+CPU80486        EQU     3
+
+;======================================================================
+;                           Key Assignments
+;======================================================================
+kESC            EQU       2
+kONE            EQU       4
+kTWO            EQU       6
+kTHREE          EQU       8
+kFOUR           EQU      10
+kFIVE           EQU      12
+kSIX            EQU      14
+kSEVEN          EQU      16
+kEIGHT          EQU      18
+kNINE           EQU      20
+kZERO           EQU      22
+kMINUS          EQU      24
+kEQUAL          EQU      26
+kBACKSPACE      EQU      28
+kTAB            EQU      30
+kQ              EQU      32
+kW              EQU      34
+kE              EQU      36
+kR              EQU      38
+kT              EQU      40
+kY              EQU      42
+kU              EQU      44
+kI              EQU      46
+kO              EQU      48
+kP              EQU      50
+kL_BRACE        EQU      52
+kR_BRACE        EQU      54
+kENTER          EQU      56
+kCTRL           EQU      58
+kA              EQU      60
+kS              EQU      62
+kD              EQU      64
+kF              EQU      66
+kG              EQU      68
+kH              EQU      70
+kJ              EQU      72
+kK              EQU      74
+kL              EQU      76
+kSEMICOLON      EQU      78
+kQUOTE          EQU      80
+kBACKQUOTE      EQU      82
+kL_SHIFT        EQU      84
+kBACKSLASH      EQU      86
+kZ              EQU      88
+kX              EQU      90
+kC              EQU      92
+kV              EQU      94
+kB              EQU      96
+kN              EQU      98
+kM              EQU     100
+kCOMMA          EQU     102
+kPERIOD         EQU     104
+kSLASH          EQU     106
+kR_SHIFT        EQU     108
+kGREY_STAR      EQU     110
+kALT            EQU     112
+kSPACE          EQU     114
+kCAPSLOCK       EQU     116
+kF1             EQU     118
+kF2             EQU     120
+kF3             EQU     122
+kF4             EQU     124
+kF5             EQU     126
+kF6             EQU     128
+kF7             EQU     130
+kF8             EQU     132
+kF9             EQU     134
+kF10            EQU     136
+kNUMLOCK        EQU     138
+kSCRLLOCK       EQU     140
+kHOME           EQU     142
+kUP             EQU     144
+kPAGE_UP        EQU     146
+kGREY_MINUS     EQU     148
+kLEFT           EQU     150
+kPAD_FIVE       EQU     152
+kRIGHT          EQU     154
+kGREY_PLUS      EQU     156
+kEND            EQU     158
+kDOWN           EQU     160
+kPAGE_DOWN      EQU     162
+kINSERT         EQU     164
+kDELETE         EQU     166
+
+kF11            EQU     174
+kF12            EQU     176
+
\ No newline at end of file
diff --git a/16/scrasm/DIAGONAL.MAP b/16/scrasm/DIAGONAL.MAP
new file mode 100644
index 0000000000000000000000000000000000000000..1fb5529e33c171ad8bbb93d881bd8933412de427
GIT binary patch
literal 65057
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

literal 0
HcmV?d00001

diff --git a/16/scrasm/DIAGONAL.PAL b/16/scrasm/DIAGONAL.PAL
new file mode 100644
index 0000000000000000000000000000000000000000..5dee1969fc3e9dfe5bee855460c512ba3a850e69
GIT binary patch
literal 768
zcmWO4fugA}007W2rBcR}O4&6{OBqvI%Gm$^)qCd~4gg>dt%dE`E^_?PL#dC+Ix03v
zg)<S7c29?d=>s=;JrU8Lq&#;GQ)M~QO6RqSZwB9WAV;TF@YMk&t+()|8fhN>SZXNw
zlH!w9V<LvA?eWkd{q)VlorK*tP+md9L3x3+uyg9he?C5<Aj3`?!8id?X6=Z#r3kSw
z;OVL+t|*qWvN{1(I~xa}_1u_+nQYxVqx4kccja2rjmU8whaB%&kWlA9V4eYzSf|K4
zW5iHc`f25o+AeOex&t9W+rr^xYvr1^KTW9DSpK5MB;_}wACiwW9vJR<(ACaUz=s5)
zvl``HN5pk_F==54)y3af9hJzsHkCsxbX1!ipSG+=R0gD3Wu=?YWt3Yuh6vC60JzTF
zh6@O6U^&3^AoA^S?WP-_U{r*-+D9Tu+Cw(vL=$RGY&!Fv)v^>#CCj>_H<jPVSZdsw
z;AI@8;d=y=vUKPDBr+oW*6D|nkre~2dLp{4eI~;r(gK?XO;^9?uDsYy0ZR(#AIOg|
z&TO2zLF_vbf;$Yhk%ba3$k2*}E=`w=SiFFBH4_5JcHRvOrR~u;dh$%~8@blaW-PIy
zVVCb^oCtiVgPc2r!4m~%VzJCC6I4ZEjnf+<cfXKs)!O0(TLp$U&=WM;o_=m`eECJq
z2bW{?KVsfzaYyiz1`p;44x1WWg~g?J=}@6UI;MY`98Hm#D%Bz$+ei(&PH&|_VhZYh
R#ih%dB`qyNVV2L5_#e4jUwr@o

literal 0
HcmV?d00001

diff --git a/16/scrasm/DIAGONAL.TIL b/16/scrasm/DIAGONAL.TIL
new file mode 100644
index 0000000000000000000000000000000000000000..95eee9f2380ee2728299c37abc96e010bb2187eb
GIT binary patch
literal 65536
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
Mxgy`7T9X6(KVmnBasU7T

literal 0
HcmV?d00001

diff --git a/16/scrasm/GENMAP.C b/16/scrasm/GENMAP.C
new file mode 100644
index 00000000..01652048
--- /dev/null
+++ b/16/scrasm/GENMAP.C
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#define WIDTH   255
+
+#define MAPNAME "Diagonal"
+#define FILENAME "%s.MAP"
+char    fn[100] = FILENAME;
+typedef unsigned char BYTE;
+typedef unsigned short int WORD;
+typedef BYTE    ROW[WIDTH];
+
+ROW     r;
+
+#define MAGIC_NUM       100
+#define SQUARE_WIDTH    16
+#define SQUARE_HEIGHT   16
+#define SCREEN_WIDTH    320
+#define SCREEN_HEIGHT   200
+#define VIRTUAL_WIDTH   352
+#define VIRTUAL_HEIGHT  240
+typedef struct MAPHEADER {
+        BYTE    name[12];       /* 12    Includes [n]=0 and [n+1]=26 */
+        WORD    width;          /*  2                                */
+        WORD    height;         /*  2                                */
+        WORD    extent;         /*  2                                */
+        WORD    off_x1;         /*  2                                */
+        WORD    off_y1;         /*  2                                */
+        WORD    off_x2;         /*  2                                */
+        WORD    off_y2;         /*  2                                */
+        WORD    x_wrap;         /*  2                                */
+        WORD    y_wrap;         /*  2                                */
+        WORD    magic;          /*  2                                */
+        } MAPHEADER, far *LPMAPHEADER;
+MAPHEADER mh;
+
+void main(int argc, char *argv[])
+        {
+        FILE    *fp;
+        int     i,j;
+        BYTE    b;
+        int     width = WIDTH;
+        int     height = WIDTH;
+
+        if (argc > 1) {
+                width = atoi(argv[1]);
+                if (width > WIDTH)
+                        width = WIDTH;
+                printf("Width = %d\n",width);
+                height=width;
+                if (argc > 2) {
+                        height = atoi(argv[2]);
+                        if (height > WIDTH)
+                                height = WIDTH;
+                        printf("Height = %d\n",height);
+                        }
+                }
+
+        sprintf(fn,FILENAME,MAPNAME);
+        fp = fopen(fn,"wb");
+        if (!fp) {
+                printf("Couldn't open %s for write.\n",fn);
+                exit(1);
+                }
+
+        memset(&mh, 0xFF, sizeof(MAPHEADER));   /* Will reveal missing initializing */
+        strcpy((char *)mh.name,MAPNAME);
+        mh.name[8]=0;
+        mh.name[9]=26;  /* Ctrl-Z */
+        mh.width = (WORD)width;
+        mh.height = (WORD)height;
+        mh.extent = (WORD)((WORD)width * (WORD)height);
+        mh.off_x1 = (WORD)0;
+        mh.off_y1 = (WORD)0;
+        mh.off_x2 = (WORD)(((VIRTUAL_WIDTH / SQUARE_WIDTH) - 1) % width);
+        mh.off_y2 = (WORD)((((VIRTUAL_HEIGHT / SQUARE_HEIGHT) - 1) % height) * width);
+        mh.x_wrap = (WORD)width;
+        mh.y_wrap = (WORD)height;
+        mh.magic = MAGIC_NUM;
+        fwrite(&mh, 1, sizeof(MAPHEADER), fp);
+
+        for (i = 0; i<width; i++) {
+                b = (BYTE)(i%width);
+                for (j = 0; j<width; j++) {
+                        r[j] = b;
+                        b = (BYTE)(((int)b+1) % width);
+                        }
+                r[0]=1;
+                if (i == 0) r[0]=0;
+                fwrite(r, width,1, fp);
+                printf("Map row %d\r",i);
+                }
+        fclose(fp);
+        printf("All done!    \n");
+        exit(0);
+        }
+
\ No newline at end of file
diff --git a/16/scrasm/GENMAP.EXE b/16/scrasm/GENMAP.EXE
new file mode 100644
index 0000000000000000000000000000000000000000..258ec9f10f79802f2e19e884e9ec945c534c1675
GIT binary patch
literal 18664
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
bn$1GF5Xx_WerKb66~fPgpZ~4ebjJP%cYq1R

literal 0
HcmV?d00001

diff --git a/16/scrasm/GENMAP.LNK b/16/scrasm/GENMAP.LNK
new file mode 100644
index 00000000..95ee9882
--- /dev/null
+++ b/16/scrasm/GENMAP.LNK
@@ -0,0 +1 @@
+genmap.obj; 
diff --git a/16/scrasm/GENMAP.OBJ b/16/scrasm/GENMAP.OBJ
new file mode 100644
index 0000000000000000000000000000000000000000..6f1e7a9dc563d3e5bf1a4ff8a99df366280a0329
GIT binary patch
literal 2543
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

literal 0
HcmV?d00001

diff --git a/16/scrasm/GENPAL.C b/16/scrasm/GENPAL.C
new file mode 100644
index 00000000..f913ae07
--- /dev/null
+++ b/16/scrasm/GENPAL.C
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#define COLORS  256
+#define PALNAME "Diagonal"
+#define FILENAME "%s.PAL"
+char    fn[100] = FILENAME;
+typedef unsigned char BYTE;
+typedef unsigned short int WORD;
+typedef struct COLOR {
+        BYTE    r,g,b;
+        } COLOR, far *LPCOLOR;
+
+void main()             /* int argc, char *argv[]) */
+        {
+        FILE    *fp;
+        int     i;
+        int     colors = COLORS;
+        COLOR   c;
+        int     r,dr,g,dg,b,db;
+
+        sprintf(fn,FILENAME,PALNAME);
+        fp = fopen(fn,"wb");
+        if (!fp) {
+                printf("Couldn't open %s for write.\n",fn);
+                exit(1);
+                }
+
+        r=0;    dr=2;
+        g=0;    dg=3;
+        b=0;    db=5;
+        for (i = 0; i < colors; i++) {
+                c.r = (BYTE)r;  r+=dr;
+                if (r > 63) { r = 63; dr = -dr; }
+                 else if (r < 0) { r = 0; dr = -dr; }
+                c.g = (BYTE)g;  g+=dg;
+                if (g > 63) { g = 63; dg = -dg; }
+                 else if (g < 0) { g = 0; dg = -dg; }
+                c.b = (BYTE)b;  b+=db;
+                if (b > 63) { b = 63; db = -db; }
+                 else if (b < 0) { b = 0; db = -db; }
+                fwrite(&c, sizeof(c),1, fp);
+                printf("Palette %d\r",i);
+                }
+        fclose(fp);
+        printf("All done!    \n");
+        exit(0);
+        }
+
\ No newline at end of file
diff --git a/16/scrasm/GENPAL.EXE b/16/scrasm/GENPAL.EXE
new file mode 100644
index 0000000000000000000000000000000000000000..c242a3d46e6f1999bc6a3190db1193e9a7c694dd
GIT binary patch
literal 17676
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

literal 0
HcmV?d00001

diff --git a/16/scrasm/GENPAL.LNK b/16/scrasm/GENPAL.LNK
new file mode 100644
index 00000000..4b4ff212
--- /dev/null
+++ b/16/scrasm/GENPAL.LNK
@@ -0,0 +1 @@
+genpal.obj; 
diff --git a/16/scrasm/GENPAL.OBJ b/16/scrasm/GENPAL.OBJ
new file mode 100644
index 0000000000000000000000000000000000000000..ae94092e11c393af00468d5bbde72ee8db2d69b4
GIT binary patch
literal 1895
zcmZ8hQD|Fb6#o8uZ*FeVWxZ{;;@sR)*E-#_tL{P6Nllwvr=&|*vdqD@YntA4aaj`Y
zz3t}EZjd0ES)dOxR64AJK8qmaRSe9By}MT*gjPzavD8pH;`wh9DF$-+&iT&y|MUOn
z`_COOlvyKJNM=V<D9gY%Y%+oS<A5|735KL#ARcf{M$X3K;zTT_Xn}J&cX@_~V;83;
zBH@@E3{4Pp4-dyLMnjHC0QZl;rN=|>#a&K(dkIOWHRRyi=OX8$_`;1dw^@(C9P|VB
zh;0P;q%PX)V))X7p=k!Vl{PjAd%O%^Dd=qpEwLqGsRt_S6Z*vgDacTE0T0G3lzV}%
zBjMoLz*HzU8h&R2We<5`geF5+z5oFTW|Fh{Tr!IhYcv`N<Hj^5^K;pm+%emqFBm!h
zh~-b`P5%uuV;iGhM3Y&=whjNtj1Pfq)<2Wa8AE>hdC^@0-+Cd$a2WtqdT00jF7|*4
zqMpu$vDk}yK6rIKnKJD;%a{R{6;S1r1Kd05P-jzDuUYmrD7sZJGdVjASx@t_;MO}1
zmu}q5*pw_W$~<3Ls{t!O;=)614UCLv%|rh%qU0^s<(j(7lJ06-#f2@{;wr#nY6G1(
zsm3};c&Kdy549bEK244`Mfx;2T6fWB1EB1Rwq4d%D%uXywu=kf<G1;elsZn#&OeXu
zYCB{TfsZ=`PiYesty$JqE7~U0n#F}?H?_%AH+kx&liKX2QW0IEqBY9epA~JLX^rAS
zV;oDzQF14QdSA7^zgj;~Ej^PE>qo2gW7X1$gj9dCS`So9p@gdxNyxZ2K=+t-TFXHy
zo3{+Q$tQ40@Pnkc>qkn(M~+8UAze>qavti{PRoQaV=4r<2{H#YIhy74R*R`Zy1?P4
z6FJKx8=Rl!XoI5+r`H{N+DCAWpq$EQ^QOgPR$8LUQUYY`fdrrG*0VF2dEM@Tz`|5u
zFYQ3J@QS60i}8?`ps3P&3rEiF#y#Y>AX}MRhHmqv3d}v9)Uz3jmXZKf)-(C(xipsC
zcr<wF(RWoWUxMoiINJ|7UC3MQ#38tEq^>4S-QG)-qIz_C1SCS;?j_r+dP$=lhtCO6
zx+Y($hc<E!faM~Ioppply`whrZm+L$p)|VPCZTnS*8CQiWlco1s;#sIt+eJhYGYm1
z7PSpl(bitmHa-zo54R{`g{xkuo$jiczlgR^zf$?*@-J9Ah|(JgcRg4wogrPkpHS-Q
zYUu-lHc4cWcf_Uheglg#KDWs3qif$s_wp1}9Kf@98mDj&r*R1H;t1l@i7ObwRbosW
z#VriuQ;c8<&*3K=!_Rmgzu^UJ;5c@00{!eooM12EEjEfNb`qD^7!39@^6V8yaSIGT
zo&sa9(|%Rj@q7620E76I@b82l6Be0@L(GQ(Hi(<Fx<s*9mKn`+uG#%GSX>a)ww@K5
zB2KGiJ^`uoQAmO;6_`kdq!(=S@5W!UWI`lf(o;Fxu{kf%P@hg(2ImXJ%Vejs$=R;$
z=5{7)?4#`{y0f8(wj76@ef-2wStifnm^9$zb1cxqkZ48%G&Y?$z@>6*@=6J}Yj$^h
z{BUg_gGc4Z6tJhWt3=1_2yGU!zz#dR^Hb3&Kb*_APt`u9Xd2fCo$S5;T~ha<we$M_
lm&a{-Xq4w6R6rkSf@8T4uJbf0cwLGjy*fHJhR+0y;a}|M+Pwe(

literal 0
HcmV?d00001

diff --git a/16/scrasm/GENSQ.C b/16/scrasm/GENSQ.C
new file mode 100644
index 00000000..402853f3
--- /dev/null
+++ b/16/scrasm/GENSQ.C
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#define WIDTH   256
+
+#define FILENAME "DIAGONAL.TIL"
+char    fn[100] = FILENAME;
+typedef unsigned char BYTE;
+typedef BYTE    ROW[16];
+typedef ROW     BITMAP[16];
+
+BITMAP  b;
+BITMAP  c;
+
+BITMAP  pattern={{1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
+                 {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+                 {1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0},
+                 {1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0},
+                 {1,0,0,1,0,0,0,0,0,0,0,2,0,0,0,0},
+                 {0,0,1,0,0,1,1,0,1,1,0,0,2,0,0,0},
+                 {0,0,1,0,0,1,2,0,1,2,0,0,2,0,0,0},
+                 {0,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0},
+                 {0,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0},
+                 {0,1,0,0,1,2,0,0,0,1,2,0,0,2,0,0},
+                 {0,0,1,0,1,2,1,1,1,1,2,0,2,0,0,0},
+                 {0,0,1,0,0,2,2,2,2,2,0,0,2,0,0,2},
+                 {0,0,0,1,0,0,0,0,0,0,0,2,0,0,0,2},
+                 {0,0,0,0,2,2,0,0,0,2,2,0,0,0,0,2},
+                 {0,0,0,0,0,0,2,2,2,0,0,0,0,0,2,2},
+                 {0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2}};
+
+void copy_pattern(BITMAP b,BITMAP patt, BYTE l, BYTE m, BYTE h)
+        {
+        int     x,y;
+
+        for (y=0; y<16; y++) {
+                for (x=0; x<16; x++) {
+                        switch (patt[y][x]) {
+                                case 0:
+                                        b[y][x] = m;
+                                        break;
+                                case 1:
+                                        b[y][x] = l;
+                                        break;
+                                case 2:
+                                        b[y][x] = h;
+                                        break;
+                                }
+                        }
+                }
+        }
+
+/* Transforms linear to planar */
+void transform(BITMAP b,BITMAP c)
+        {
+        int     x,y,p;
+        BYTE    *pb = (BYTE *)c;
+
+        for (p=0; p<4; p++) {
+                for (y=0; y<16; y++) {
+                        for (x=0; x<16; x+=4) {
+                                *(pb++) = b[y][x+p];
+                                }
+                        }
+                }
+        }
+
+void main(int argc,char *argv[])
+        {
+        FILE    *fp;
+        int     i;
+        int     width = WIDTH;
+
+        fp = fopen(fn,"wb");
+        if (!fp) {
+                printf("Couldn't open %s for write.\n",fn);
+                exit(1);
+                }
+        if (argc > 1) {
+                width = atoi(argv[1]);
+                if (width > WIDTH)
+                        width = WIDTH;
+                printf("Width = %d\n",width);
+                }
+
+        for (i = 0; i< width; i++) {
+                BYTE    less,more;
+
+                less = (BYTE)((i + width - 1) % width);
+                more = (BYTE)((i + 1) % width);
+                copy_pattern(b, pattern, less, (BYTE)i, more);
+                transform(b,c);
+                fwrite(c, 16,16, fp);
+                printf("Square %d\r",i);
+                }
+        fclose(fp);
+        printf("All done!     \n");
+        exit(0);
+        }
+
\ No newline at end of file
diff --git a/16/scrasm/GENSQ.EXE b/16/scrasm/GENSQ.EXE
new file mode 100644
index 0000000000000000000000000000000000000000..71cf2657d4497bdedfdf4c4c967725933c1a712d
GIT binary patch
literal 18916
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

literal 0
HcmV?d00001

diff --git a/16/scrasm/GENSQ.LNK b/16/scrasm/GENSQ.LNK
new file mode 100644
index 00000000..a9d9b795
--- /dev/null
+++ b/16/scrasm/GENSQ.LNK
@@ -0,0 +1 @@
+gensq.obj; 
diff --git a/16/scrasm/GENSQ.OBJ b/16/scrasm/GENSQ.OBJ
new file mode 100644
index 0000000000000000000000000000000000000000..7166ee65a0b5b4b887152b5f1a6c063a68ee08d3
GIT binary patch
literal 2977
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

literal 0
HcmV?d00001

diff --git a/16/scrasm/INIT.INC b/16/scrasm/INIT.INC
new file mode 100644
index 00000000..eddeeed4
--- /dev/null
+++ b/16/scrasm/INIT.INC
@@ -0,0 +1,375 @@
+;; Error messages
+ERR_OK          EQU     0
+msgErr0         db      'Later!',13,10,'$'
+ERR_MEM         EQU     1
+msgErr1         db      'Error 001:  Out of memory?',13,10,'$'
+ERR_CPU         EQU     2
+msgErr2         db      'Error 002:  CPU must be at least an 80386.',13,10,'$'
+ERR_FILE        EQU     3
+msgErr3         db      'Error 003:  File error.',13,10,'$'
+ERR_FILENOTFOUND EQU    4
+msgErr4         db      'Error 004:  File not found.',13,10,'$'
+msgtblError     dw      offset msgErr0, offset msgErr1, offset msgErr2,
+                        offset msgErr3, offset msgErr4
+nError          db      0
+
+;; CPU name strings
+CPUName86       DB      "8088/8086$"
+CPUName286      DB      "80286DX/SX$"
+CPUName386      DB      "80386DX/SX$"
+CPUName486      DB      "80486DX/SX or better$"
+CPUNameTable    DW      CPUName86,CPUName286,CPUName386,CPUName486
+
+EVEN
+msgCPUTypeIs    DB      "Your CPU type:  $"
+EVEN
+msgCPUTypeIsEnd DB      13,10,'$'
+nCPU            DB      0
+
+EVEN
+msgPages        DB      'Pages displayed:  '
+strNumPages     DB      6 dup (?),13,10,'$'
+
+EVEN
+bufText         DW      80*50 DUP (?)   ; Needs this much to hold
+                                        ; a 50-line screen...
+wCPos           DW      0
+nDisplay        DB      0
+
+EVEN
+fnMap1          db      'DIAGONAL.MAP',0
+fnTiles1        db      'DIAGONAL.TIL',0
+fnPalette       db      'DIAGONAL.PAL',0        ; only one allowed, for now
+fnMap2          db      'SCROLL.MAP',0
+fnTiles2        db      'SCROLL.TIL',0
+
+fntblMap        dw      offset fnMap1,offset fnMap2
+fntblTiles      dw      offset fnTiles1,offset fnTiles2
+nMap            dw      0
+
+;; CPUType routine snatched from Ray Duncan's _Power Programming MASM_
+;; chapter 14.  Reformatted to my style, but I left the code alone
+;; except that it used to push a bunch of stuff, but doesn't any more
+;; because I don't care what gets destroyed.
+CPUType         PROC    near
+                pushf                   ; now try to clear bits 12-15
+                pop     ax              ; of CPU flags
+                and     ax,0fffh
+                push    ax              ; set modified CPU flags
+                popf
+                pushf
+                pop     ax              ; get flags again
+                and     ax,0f000h       ; if bits 12-15 are still
+                cmp     ax,0f000h       ; set, this is 8086/88
+                jne     cpu1            ; jump, not 8086/88
+                mov     nCPU,CPU8086    ; set nCPU = 86/88 CPU type
+                jmp     cpux            ; and exit
+
+cpu1:           or      ax,0f000h       ; must be 286 or later,
+                push    ax              ; now try to set bits 12-15
+                popf                    ; of CPU flags
+                pushf
+                pop     ax              ; if bits 12-15 can't be
+                and     ax,0f000h       ; set, this is a 286
+                jnz     cpu2            ; jump, not 80286
+                mov     nCPU,CPU80286   ; set nCPU = 286 CPU type
+                jmp     cpux            ; and exit
+
+cpu2:           mov     bx,sp           ; 386 or later, save SP
+                and     sp,not 3        ; avoid stack alignment fault
+                pushfd                  ; get value of EFLAGS
+                pop     eax
+                mov     ecx,eax         ; save copy of EFLAGS
+                xor     eax,40000h      ; flip AC bit in EFLAGS
+                push    eax             ; try and force EFLAGS
+                popfd
+                pushfd                  ; get back EFLAGS value
+                pop     eax
+                mov     sp,bx           ; restore old stack pointer
+                xor     eax,ecx         ; can AC bit be changed?
+                jnz     cpu3            ; no, jump, not a 386
+                mov     nCPU,CPU80386   ; set nCPU = 386 CPU type
+                jmp     cpux            ; and exit
+
+cpu3:           mov     nCPU,CPU80486   ; set nCPU = 486 CPU type
+
+cpux:           mov     bl,nCPU
+                xor     bh,bh
+                shl     bx,1
+                DOSPRINT <offset msgCPUTypeIs>
+                DOSPRINT CPUNameTable[bx]
+                DOSPRINT <offset msgCPUTypeIsEnd>
+                ret                     ; return with nCPU = CPU type
+CPUType         ENDP
+
+;; Initialize:  So far, all it does is make sure you have a 386 +
+;; (because that's what I assembled the code for).
+Initialize      PROC    near
+        ; Set DS = CS in this program, since data is local
+                mov     ax,cs
+                mov     segCode,ax      ; Store the Code Segment
+                mov     bx,ds
+                mov     segPSP,bx       ; Store the PSP Segment
+                mov     ds,ax           ; Set DS = CS
+
+        ; Resize code to 64K
+        CODE_SIZE EQU 64                ; <- this is arbitrary.
+                ; ES already -> allocated segment
+                mov     ah,4ah
+                mov     bx,64*CODE_SIZE
+                int     21h
+                mov     nError,ERR_MEM
+                jc      TerminateError
+
+;; I've chosen not to implement sprites yet so that I can get this out
+;; the door...
+;; ; 320x200 buffer for sprite drawing.  To draw sprites, first draw them
+;; ; into this buffer, adding rectangles to the current rectangle list.
+;; ; Then, use BUFFER_COPY to put out the buffers with the current
+;; ; rectangle list to the screen.  BUFFER_COPY will ensure minimal VGA
+;; ; writing.
+;;         ; Create a buffer segment
+;;                 mov     bx,(320 * 200) / 16
+;;                 mov     ah,48h
+;;                 int     21h
+;;                 mov     nError,ERR_MEM
+;;                 jc      TerminateError
+;;                 mov     segBuffer,ax
+
+                call    CPUType
+                mov     nError,ERR_CPU
+                cmp     nCPU,2
+                jl      TerminateError
+
+                mov     ds,segCode
+                mov     dx,offset fnPalette
+                call    LoadPaletteFile
+                jc      TerminateError
+
+                call    LoadIndex
+                jc      TerminateError
+
+                KEYB_START
+
+                call    Beginning       ; Can display an entry screen here
+
+        ; This is linked in from Michael Abrash's zen timer code.
+        ; (But I wrote the Click myself)
+        call    Click
+        call    ZTimerOn
+
+                call    MainLoop
+
+        call    ZTimerOff
+        call    Click
+
+                call    Ending          ; Can display an exit screen here
+
+                KEYB_END
+
+Terminate:      mov     nError,ERR_OK
+TerminateError:
+                mov     ax,cs   ;DOS functions require that DS point
+                mov     ds,ax   ; to text to be displayed on the screen
+                mov     bh,0
+                mov     bl,nError
+                shl     bx,1
+                DOSPRINT msgtblError[bx]
+
+                mov     ax,pages
+                mov     ds,segCode
+                mov     si,offset strNumPages
+                call    Int2Ascii
+                DOSPRINT <offset msgPages>
+
+        call    ZTimerReport
+
+                mov     al,nError
+                mov     ah,4ch        ; DOS Terminate
+                int     21h
+                ; Don't need to RET!  We're outta here
+Initialize      ENDP
+
+;; Clicks the internal speaker.  I use this to indicate that page timing
+;; has started.
+Click           PROC
+                in      al,61h
+                mov     ah,al
+                or      al,3
+                out     61h,al
+
+                mov     cx,5000         ; (this is an arbitrary delay!)
+spkr_on:        loop    spkr_on
+                mov     al,ah
+                out     61h,al
+                ret
+Click           ENDP
+
+;; Copied from an old 8088 "Learn Assembly" book and changed a bit
+Int2Ascii       PROC
+                mov     cx,6
+                mov     byte ptr cs:[si],' '
+                mov     byte ptr cs:[si+1],'0'
+                mov     byte ptr cs:[si+2],'0'
+                mov     byte ptr cs:[si+3],'0'
+                mov     byte ptr cs:[si+4],'0'
+                mov     byte ptr cs:[si+5],'0'
+                add     si,6
+                mov     cx,10
+                or      ax,ax
+                jns     clear_divide
+                neg     ax
+                mov     byte ptr cs:[si-6],'-'
+clear_divide:   mov     dx,0
+                div     cx
+                add     dx,'0'
+                dec     si
+                mov     cs:[si],dl
+                or      ax,ax
+                jnz     clear_divide
+                ret
+Int2Ascii       ENDP
+
+;; Given a filename at DS:DX, reads the file into memory and returns
+;; a pointer to it as DX:0000.
+;; Note that this routine obviously will only work correctly for
+;; a file < 640k in size, but you can bring in files bigger than 64k.
+;; This code comes from Future Crew's STMIK sampler "Mental Surgery"
+;; and I commented it up to make it fit in with my stuff a little better.
+;; Thank you, FC, for releasing that code!  Several of the routines
+;; in this program were inspired or helped along by having that source...
+;; Most recently, added in error codes.
+EVEN
+LoadFile        PROC    NEAR
+                ;set: DX=offset to filename
+                ;return: DX=segment of file
+
+        ; Open the datafile at DS:DX.
+                mov     ax,3D00h        ; 3D,00 -> Open file, read only
+                                        ; DS:DX already points at filename
+                int     21h             ;  returns AX=file handle
+                mov     cl,ERR_FILENOTFOUND
+                jc      ferror
+                mov     bx,ax           ; Store file handle in BX
+                mov     si,bx           ; and also in a variable
+
+        ; Get the length of the file so we know how much to allocate
+                mov     ax,4202h        ; 42,02 -> Seek, signed from end
+                mov     cx,0            ; CX:DX is a long file offset,
+                                        ; BX is already set as file handle
+                mov     dx,0            ;  zero in this case = end of file
+                int     21h             ; (returns long offset in DX:AX)
+                mov     cl,ERR_FILE
+                jc      ferror
+
+;;;             shr     dx,1            ; This is original FC code,
+;;;             rcr     ax,1            ; which I removed because the
+;;;             shr     dx,1            ; 386 has a nice instruction
+;;;             rcr     ax,1            ; to do this all!
+;;;             shr     dx,1            ; But 286 users will want to
+;;;             rcr     ax,1            ; return to this code, instead
+;;;             shr     dx,1            ; of SHRD dx,ax,4
+;;;             rcr     ax,1            ;
+
+        ; Now turn that long DX:AX into a number of paragraphs to allocate
+        ; for when we read the file.
+                shrd    ax,dx,4         ; Divides long DX:AX by 4,
+                mov     bx,ax           ;  and stores this in BX
+                inc     bx      ; HHMMMM?  One more needed for small #'s
+                mov     ah,48h          ; 48 -> Allocate memory
+                                        ; BX already = # of paragraphs
+                int     21h
+                mov     cl,ERR_MEM
+                jc      ferror
+                mov     di,ax           ; store this in a variable
+
+        ; Seek the file back to the beginning in order to read it into
+        ; the memory we just allocated.
+                mov     ax,4200h        ; 42,00 -> Seek, absolute offset
+                mov     bx,si           ; BX is the file handle.
+                mov     cx,0            ; CX:DX is a long offset
+                mov     dx,0
+                int     21h
+                jc      ferror
+
+        ; Now read the file into memory
+                mov     ds,di           ; DS points at alloc'd memory
+ReadBlock:      mov     ah,3fh          ; 3F -> Read file
+                mov     cx,32768        ; read 32768 bytes at a time
+                mov     dx,0            ; DS:DX points at beginning of
+                int     21h             ;  this block of memory.
+                mov     cl,ERR_FILE
+                jc      ferror
+                mov     dx,ds           ; Offset DS by (32768/16), which
+                add     dx,800h         ;  is the number of paragraphs in
+                mov     ds,dx           ;  each block of 32768 bytes.
+                cmp     ax,32768        ; Did we actually read 32768 bytes?
+                je      ReadBlock       ; If so, there's more to read...
+                                        ; Otherwise, we've read all the
+                                        ;  data in the file.
+
+        ; So now, close the file handle.
+                mov     ah,3Eh          ; 3E -> Close file
+                                        ; BX still is the file handle
+                int     21h
+
+        ; Everything went ok.  Return the segment in DX.
+                mov     dx,di
+                mov     nError,ERR_OK
+                ret
+ferror:         mov     nError,cl
+                ret
+LoadFile        ENDP
+
+;; Eventually, this should load in an index of all data files to
+;; allow for filenames to be specified outside of the program.  The
+;; goal is to make the program have no hardcoded filenames...
+;; Of course, the structure of this index and its entries will be
+;; hardcoded, as will the structures of all of the files it includes.
+LoadIndex       PROC    near
+                ret
+LoadIndex       ENDP
+
+;; Save the current video mode and cursor position with standard
+;; BIOS calls
+SaveVideo       PROC    near
+                mov     ah,0Fh
+                int     10h             ; Get current display Mode
+                mov     nDisplay,al
+                mov     ah,03h
+                mov     bh,0
+                int     10h
+                mov     wCPos,dx
+
+                mov     ds,segText
+                mov     si,0
+                mov     es,segCode
+                mov     di,offset bufText
+                mov     cx,80*50
+            rep movsw
+                ret
+SaveVideo       ENDP
+
+;; Restore the current video mode and cursor position with standard
+;; BIOS calls
+RestoreVideo    PROC    near
+                mov     ah,00h
+                mov     al,nDisplay
+                int     10h             ; Get current display Mode
+                mov     ah,02h
+                mov     bh,0
+                mov     dx,wCPos
+                int     10h
+
+                PAL_UPDATE      ; When flipping into text mode, re-do the
+                                ; palette because the BIOS changes it.
+
+                mov     es,segText
+                mov     di,0
+                mov     ds,segCode
+                mov     si,offset bufText
+                mov     cx,80*50
+            rep movsw
+                ret
+RestoreVideo    ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/KEYB.INC b/16/scrasm/KEYB.INC
new file mode 100644
index 00000000..ef730cf0
--- /dev/null
+++ b/16/scrasm/KEYB.INC
@@ -0,0 +1,237 @@
+;; ====================================================================
+;; Macros
+;; ====================================================================
+;; Jump if key pressed
+JKEYP           MACRO   key,label
+                cmp     byte ptr cs:_keyFlags[key+1],1
+                je      label
+                ENDM
+;; Jump if key not pressed
+JKEYNP          MACRO   key,label
+                cmp     byte ptr cs:_keyFlags[key+1],1
+                jne     label
+                ENDM
+
+;; Note that JNKEY and JKEY both modify _flKeyChanged, so you cannot
+;; use one after the other!  In other words,
+;;  JKEYNP no_key
+;;  JKEYP  yes_key      ;<-- this will fail
+;; will not work like you'd think it would.  The second call (JKEYP)
+;; will not know that a key has been pressed!
+;; Jump if no key pressed:
+JNKEY           MACRO   label
+                cmp     cs:_flKeyChanged,0
+                je      label
+                mov     cs:_flKeyChanged,0      ; <--- important!
+                ENDM
+;; Jump if key pressed:
+JKEY            MACRO   label
+                cmp     cs:_flKeyChanged,0
+                mov     cs:_flKeyChanged,0
+                jne     label
+                ENDM
+
+;; Start keyboard interrupts
+KEYB_START      MACRO
+                call    SwapInt9
+                mov     cs:_flKeyChanged,0
+                ENDM
+
+;; Clear keyboard interrupts
+KEYB_END        MACRO
+                call    SwapInt9
+                ENDM
+
+;; Credit for these routines:  Steve Dollins, Brown Computer Group.
+;; I didn't write any of the code below -- just heisted it from some
+;; stuff that he wrote and released!  Very useful keyboard routines.
+;; Any comments prefixed SDE were added by me.
+_keyFlags       dw      256 dup (0)     ; SDE: since they only use 2 bits
+                                        ; per word, this is a tradeoff,
+                                        ; space for time
+
+oldint9_offset  dw      offset newint9
+oldint9_segment dw      seg newint9
+
+_flKeyChanged   dw      0
+
+;-----------------------------------------------------------------------
+; void SwapInt9( void )
+;
+;       SwapInt9() exchanges the vector in oldint9_segment:oldint9_offset
+;       with the vector in the interrupt table for INT 9h.
+;-----------------------------------------------------------------------
+
+SwapInt9        PROC    far
+                mov     ax,cs
+                mov     ds,ax
+
+                mov     ax,03509h       ; Get interrupt 09h
+                int     21h             ;   return in ES:BX
+
+                mov     ax,oldint9_segment
+                mov     dx,oldint9_offset
+                push    ds
+                mov     ds,ax
+                mov     ax,02509h       ; Set new interrupt
+                int     21h             ;  to address in DS:DX
+                pop     ds
+
+                mov     oldint9_segment,es    ; Save the old interrupt
+                mov     oldint9_offset,bx
+                ret
+SwapInt9        ENDP
+
+
+;-----------------------------------------------------------------------
+; newint9 is the new keyboard interrupt (INT 9h).
+;
+;       Reads the scan code from the keyboard and modifies the key
+;       flags table.  The high byte is set to the position of the key,
+;       pressed=1, release=0.  The low byte is set to 1 when the key
+;       is pressed and left unmodified when the key is released.
+;-----------------------------------------------------------------------
+newint9         PROC    far
+                push    ax
+                push    bx
+                push    ds
+
+                mov     ax,cs
+                mov     ds,ax
+
+                JKEYNP  kCTRL,not_ctrlaltdel    ; SDE code
+                JKEYNP  kALT,not_ctrlaltdel     ; To still allow ctrl-
+                JKEYNP  kDELETE,not_ctrlaltdel  ; alt-delete.  Nothing
+                jmp     ctrlaltdel      ; worse than a total lockup!
+not_ctrlaltdel:
+
+                in      ax,60h          ; get scan code in AL, control byte in AH
+                mov     bx,ax           ; save a copy in BX
+                xchg    ah,al           ; swap to get control byte in AL
+                or      al,80h          ; clear keyboard
+                out     61h,al          ;   of interrupt
+                and     al,7Fh
+                out     61h,al
+                mov     al,20h          ; send generic EOI to
+                out     20h,al          ;   PIC
+
+                and     bx,0007fh       ; strip all but the scan code
+                shl     bx,1            ; multiply by two to get our offset
+
+                ; if the key was released, the high bit is set in the scan code
+                bt      ax,15           ; move this high bit into the carry flag
+                setnc   byte ptr [_keyFlags+bx+1] ; set "Is being pressed" flag
+                jc      short int09done ; if the key was released, we're done
+                mov     byte ptr [_keyFlags+bx],1 ; set "Has been pressed" flag
+                mov     _flKeyChanged,1         ; state of keyboard has changed
+int09done:
+                mov     _flKeyChanged,1         ; state of keyboard has changed
+                pop     ds
+                pop     bx
+                pop     ax
+                iret
+ctrlaltdel:     int     19h                     ; SDE -- added this.
+                                                ;  Allows a reboot.
+newint9         ENDP
+
+;; Defines the current key procedure (used as a jump-through)
+kprocCur        dw      KprocDirect
+
+;; This is a keyboard procedure.  Normally, this would control some
+;; sprite, or something, and the screen would follow the sprite.  For
+;; the purposes of this code, though (namely, sprite-less scrolling)
+;; it just directly affects ScrollDX and ScrollDY.
+;; This keyproc is inertialess, use + and - to increase speed and
+;; the up/down/left/right keys to move directions.
+;; Pressing K will switch to the other keyprocedure on the fly.
+;; P pauses the screen -- note that this is just for completely
+;; freezing the screen... it doesn't return until you let go!
+
+EVEN
+scroll_speed_x  dw      SCROLL_SPEED                    ; (defaults)
+scroll_speed_y  dw      SCROLL_SPEED * VIRTUAL_WIDTH    ; (defaults)
+KprocDirect     PROC    near
+chk_leftright:  mov     ax,0
+                JKEYNP  kRIGHT,not_right
+                mov     ax,scroll_speed_x
+                mov     ScrollDX,ax
+                jmp     chk_updown
+not_right:      JKEYNP  kLEFT,not_left
+                sub     ax,scroll_speed_x
+                mov     ScrollDX,ax
+                jmp     chk_updown
+not_left:       mov     ScrollDX,ax
+
+chk_updown:     mov     ax,0
+                JKEYNP  kUP,not_up
+                sub     ax,scroll_speed_y
+                mov     ScrollDY,ax
+                jmp     chk_other
+not_up:         JKEYNP  kDOWN,not_down
+                mov     ax,scroll_speed_y
+                mov     ScrollDY,ax
+                jmp     chk_other
+not_down:       mov     ScrollDY,ax
+
+chk_other:      JKEYNP  kK,not_k
+                mov     kprocCur,KprocInertia
+not_k:          JKEYNP  kM,not_m
+                mov     bDoTransition,1
+not_m:          JKEYNP  kGREY_MINUS,not_minus
+                cmp     scroll_speed_x,1
+                jle     not_minus
+                dec     scroll_speed_x
+                sub     scroll_speed_y,VIRTUAL_WIDTH
+not_minus:      JKEYNP  kGREY_PLUS,not_plus
+                cmp     scroll_speed_x,16
+                jge     not_plus
+                inc     scroll_speed_x
+                add     scroll_speed_y,VIRTUAL_WIDTH
+not_plus:
+
+pause_key:      JKEYP   kP,pause_key
+
+                ret
+KprocDirect     ENDP
+
+;; This keyproc has inertia, so + and - don't work.
+;; Use up/down/left/right keys to increase speed in those directions.
+;; Pressing K will switch to the other keyprocedure on the fly.
+;; P pauses the screen -- note that this is just for completely
+;; freezing the screen... it doesn't return until you let go!
+KprocInertia    PROC    near
+chk2_leftright: JKEYNP  kRIGHT,not2_right
+                cmp     ScrollDX,16
+                je      not2_right
+                inc     ScrollDX
+                jmp     chk2_updown
+not2_right:     JKEYNP  kLEFT,not2_left
+                cmp     ScrollDX,-16
+                je      not2_left
+                dec     ScrollDX
+                jmp     chk2_updown
+not2_left:
+
+chk2_updown:    JKEYNP  kUP,not2_up
+                cmp     ScrollDY,-VIRTUAL_WIDTH * 16
+                je      not2_up
+                add     ScrollDY,-VIRTUAL_WIDTH
+                jmp     chk2_other
+not2_up:        JKEYNP  kDOWN,not2_down
+                cmp     ScrollDY,VIRTUAL_WIDTH * 16
+                je      not2_down
+                add     ScrollDY,VIRTUAL_WIDTH
+                jmp     chk2_other
+not2_down:
+
+chk2_other:     JKEYNP  kK,not2_k
+                mov     kprocCur,KprocDirect
+not2_k:         JKEYNP  kM,not2_m
+                mov     bDoTransition,1
+not2_m:
+
+pause2_key:     JKEYP   kP,pause2_key
+
+                ret
+KprocInertia    ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/LZTIMER.ASM b/16/scrasm/LZTIMER.ASM
new file mode 100644
index 00000000..5fed7be1
--- /dev/null
+++ b/16/scrasm/LZTIMER.ASM
@@ -0,0 +1,636 @@
+;
+; *** Listing 2-5 ***
+;
+; The long-period Zen timer. (LZTIMER.ASM)
+; Uses the 8253 timer and the BIOS time-of-day count to time the
+; performance of code that takes less than an hour to execute.
+; Because interrupts are left on (in order to allow the timer
+; interrupt to be recognized), this is less accurate than the
+; precision Zen timer, so it is best used only to time code that takes
+; more than about 54 milliseconds to execute (code that the precision
+; Zen timer reports overflow on). Resolution is limited by the
+; occurrence of timer interrupts.
+;
+; By Michael Abrash 4/26/89
+;
+; Externally callable routines:
+;
+;  ZTimerOn: Saves the BIOS time of day count and starts the
+;       long-period Zen timer.
+;
+;  ZTimerOff: Stops the long-period Zen timer and saves the timer
+;       count and the BIOS time-of-day count.
+;
+;  ZTimerReport: Prints the time that passed between starting and
+;       stopping the timer.
+;
+; Note: If either more than an hour passes or midnight falls between
+;       calls to ZTimerOn and ZTimerOff, an error is reported. For
+;       timing code that takes more than a few minutes to execute,
+;       either the DOS TIME command in a batch file before and after
+;       execution of the code to time or the use of the DOS
+;       time-of-day function in place of the long-period Zen timer is
+;       more than adequate.
+;
+; Note: The PS/2 version is assembled by setting the symbol PS2 to 1.
+;       PS2 must be set to 1 on PS/2 computers because the PS/2's
+;       timers are not compatible with an undocumented timer-stopping
+;       feature of the 8253; the alternative timing approach that
+;       must be used on PS/2 computers leaves a short window
+;       during which the timer 0 count and the BIOS timer count may
+;       not be synchronized. You should also set the PS2 symbol to
+;       1 if you're getting erratic or obviously incorrect results.
+;
+; Note: When PS2 is 0, the code relies on an undocumented 8253
+;       feature to get more reliable readings. It is possible that
+;       the 8253 (or whatever chip is emulating the 8253) may be put
+;       into an undefined or incorrect state when this feature is
+;       used.
+;
+;     ***************************************************************
+;     * If your computer displays any hint of erratic behavior      *
+;     * after the long-period Zen timer is used, such as the floppy *
+;     * drive failing to operate properly, reboot the system, set   *
+;     * PS2 to 1 and leave it that way!                             *
+;     ***************************************************************
+;
+; Note: Each block of code being timed should ideally be run several
+;       times, with at least two similar readings required to
+;       establish a true measurement, in order to eliminate any
+;       variability caused by interrupts.
+;
+; Note: Interrupts must not be disabled for more than 54 ms at a
+;       stretch during the timing interval. Because interrupts
+;       are enabled, keys, mice, and other devices that generate
+;       interrupts should not be used during the timing interval.
+;
+; Note: Any extra code running off the timer interrupt (such as
+;       some memory-resident utilities) will increase the time
+;       measured by the Zen timer.
+;
+; Note: These routines can introduce inaccuracies of up to a few
+;       tenths of a second into the system clock count for each
+;       code section timed. Consequently, it's a good idea to
+;       reboot at the conclusion of timing sessions. (The
+;       battery-backed clock, if any, is not affected by the Zen
+;       timer.)
+;
+; All registers and all flags are preserved by all routines.
+;
+                DOSSEG
+                .model  small
+                .code
+        public  ZTimerOn, ZTimerOff, ZTimerReport
+
+;
+; Set PS2 to 0 to assemble for use on a fully 8253-compatible
+; system; when PS2 is 0, the readings are more reliable if the
+; computer supports the undocumented timer-stopping feature,
+; but may be badly off if that feature is not supported. In
+; fact, timer-stopping may interfere with your computer's
+; overall operation by putting the 8253 into an undefined or
+; incorrect state.  Use with caution!!!
+;
+; Set PS2 to 1 to assemble for use on non-8253-compatible
+; systems, including PS/2 computers; when PS2 is 1, readings
+; may occasionally be off by 54 ms, but the code will work
+; properly on all systems.
+;
+; A setting of 1 is safer and will work on more systems,
+; while a setting of 0 produces more reliable results in systems
+; which support the undocumented timer-stopping feature of the
+; 8253. The choice is yours.
+;
+PS2     equ     1
+;
+; Base address of the 8253 timer chip.
+;
+BASE_8253               equ     40h
+;
+; The address of the timer 0 count registers in the 8253.
+;
+TIMER_0_8253            equ     BASE_8253 + 0
+;
+; The address of the mode register in the 8253.
+;
+MODE_8253               equ     BASE_8253 + 3
+;
+; The address of the BIOS timer count variable in the BIOS
+; data segment.
+;
+TIMER_COUNT             equ     46ch
+;
+; Macro to emulate a POPF instruction in order to fix the bug in some
+; 80286 chips which allows interrupts to occur during a POPF even when
+; interrupts remain disabled.
+;
+MPOPF macro
+        local   p1, p2
+        jmp short p2
+p1:     iret                    ;jump to pushed address & pop flags
+p2:     push    cs              ;construct far return address to
+        call    p1              ; the next instruction
+        endm
+
+;
+; Macro to delay briefly to ensure that enough time has elapsed
+; between successive I/O accesses so that the device being accessed
+; can respond to both accesses even on a very fast PC.
+;
+DELAY   macro
+        jmp     $+2
+        jmp     $+2
+        jmp     $+2
+        endm
+
+StartBIOSCountLow       dw      ?       ;BIOS count low word at the
+                                        ; start of the timing period
+StartBIOSCountHigh      dw      ?       ;BIOS count high word at the
+                                        ; start of the timing period
+EndBIOSCountLow         dw      ?       ;BIOS count low word at the
+                                        ; end of the timing period
+EndBIOSCountHigh        dw      ?       ;BIOS count high word at the
+                                        ; end of the timing period
+EndTimedCount           dw      ?       ;timer 0 count at the end of
+                                        ; the timing period
+ReferenceCount          dw      ?       ;number of counts required to
+                                        ; execute timer overhead code
+;
+; String printed to report results.
+;
+OutputStr       label   byte
+                db      0dh, 0ah, 'Timed count: '
+TimedCountStr   db      10 dup (?)
+                db      ' microseconds', 0dh, 0ah
+                db      '$'
+;
+; Temporary storage for timed count as it's divided down by powers
+; of ten when converting from doubleword binary to ASCII.
+;
+CurrentCountLow         dw      ?
+CurrentCountHigh        dw      ?
+;
+; Powers of ten table used to perform division by 10 when doing
+; doubleword conversion from binary to ASCII.
+;
+PowersOfTen     label   word
+        dd      1
+        dd      10
+        dd      100
+        dd      1000
+        dd      10000
+        dd      100000
+        dd      1000000
+        dd      10000000
+        dd      100000000
+        dd      1000000000
+PowersOfTenEnd  label   word
+;
+; String printed to report that the high word of the BIOS count
+; changed while timing (an hour elapsed or midnight was crossed),
+; and so the count is invalid and the test needs to be rerun.
+;
+TurnOverStr     label   byte
+        db      0dh, 0ah
+        db      '****************************************************'
+        db      0dh, 0ah
+        db      '* Either midnight passed or an hour or more passed *'
+        db      0dh, 0ah
+        db      '* while timing was in progress. If the former was  *'
+        db      0dh, 0ah
+        db      '* the case, please rerun the test; if the latter   *'
+        db      0dh, 0ah
+        db      '* was the case, the test code takes too long to    *'
+        db      0dh, 0ah
+        db      '* run to be timed by the long-period Zen timer.    *'
+        db      0dh, 0ah
+        db      '* Suggestions: use the DOS TIME command, the DOS   *'
+        db      0dh, 0ah
+        db      '* time function, or a watch.                       *'
+        db      0dh, 0ah
+        db      '****************************************************'
+        db      0dh, 0ah
+        db      '$'
+
+;********************************************************************
+;* Routine called to start timing.                                  *
+;********************************************************************
+
+ZTimerOn        proc    near
+
+;
+; Save the context of the program being timed.
+;
+        push    ax
+        pushf
+;
+; Set timer 0 of the 8253 to mode 2 (divide-by-N), to cause
+; linear counting rather than count-by-two counting. Also stops
+; timer 0 until the timer count is loaded, except on PS/2
+; computers.
+;
+        mov     al,00110100b    ;mode 2
+        out     MODE_8253,al
+;
+; Set the timer count to 0, so we know we won't get another
+; timer interrupt right away.
+; Note: this introduces an inaccuracy of up to 54 ms in the system
+; clock count each time it is executed.
+;
+        DELAY
+        sub     al,al
+        out     TIMER_0_8253,al         ;lsb
+        DELAY
+        out     TIMER_0_8253,al         ;msb
+;
+; In case interrupts are disabled, enable interrupts briefly to allow
+; the interrupt generated when switching from mode 3 to mode 2 to be
+; recognized. Interrupts must be enabled for at least 210 ns to allow
+; time for that interrupt to occur. Here, 10 jumps are used for the
+; delay to ensure that the delay time will be more than long enough
+; even on a very fast PC.
+;
+        pushf
+        sti
+        rept 10
+        jmp     $+2
+        endm
+        MPOPF
+;
+; Store the timing start BIOS count.
+; (Since the timer count was just set to 0, the BIOS count will
+; stay the same for the next 54 ms, so we don't need to disable
+; interrupts in order to avoid getting a half-changed count.)
+;
+        push    ds
+        sub     ax,ax
+        mov     ds,ax
+        mov     ax,ds:[TIMER_COUNT+2]
+        mov     cs:[StartBIOSCountHigh],ax
+        mov     ax,ds:[TIMER_COUNT]
+        mov     cs:[StartBIOSCountLow],ax
+        pop     ds
+;
+; Set the timer count to 0 again to start the timing interval.
+;
+        mov     al,00110100b            ;set up to load initial
+        out     MODE_8253,al            ; timer count
+        DELAY
+        sub     al,al
+        out     TIMER_0_8253,al         ;load count lsb
+        DELAY
+        out     TIMER_0_8253,al         ;load count msb
+;
+; Restore the context of the program being timed and return to it.
+;
+        MPOPF
+        pop     ax
+        ret
+
+ZTimerOn        endp
+
+;********************************************************************
+;* Routine called to stop timing and get count.                     *
+;********************************************************************
+
+ZTimerOff proc  near
+
+;
+; Save the context of the program being timed.
+;
+        pushf
+        push    ax
+        push    cx
+;
+; In case interrupts are disabled, enable interrupts briefly to allow
+; any pending timer interrupt to be handled. Interrupts must be
+; enabled for at least 210 ns to allow time for that interrupt to
+; occur. Here, 10 jumps are used for the delay to ensure that the
+; delay time will be more than long enough even on a very fast PC.
+;
+        sti
+        rept    10
+        jmp     $+2
+        endm
+
+;
+; Latch the timer count.
+;
+
+if PS2
+
+        mov     al,00000000b
+        out     MODE_8253,al            ;latch timer 0 count
+;
+; This is where a one-instruction-long window exists on the PS/2.
+; The timer count and the BIOS count can lose synchronization;
+; since the timer keeps counting after it's latched, it can turn
+; over right after it's latched and cause the BIOS count to turn
+; over before interrupts are disabled, leaving us with the timer
+; count from before the timer turned over coupled with the BIOS
+; count from after the timer turned over. The result is a count
+; that's 54 ms too long.
+;
+
+else
+
+;
+; Set timer 0 to mode 2 (divide-by-N), waiting for a 2-byte count
+; load, which stops timer 0 until the count is loaded. (Only works
+; on fully 8253-compatible chips.)
+;
+        mov     al,00110100b            ;mode 2
+        out     MODE_8253,al
+        DELAY
+        mov     al,00000000b            ;latch timer 0 count
+        out     MODE_8253,al
+
+endif
+
+        cli                             ;stop the BIOS count
+;
+; Read the BIOS count. (Since interrupts are disabled, the BIOS
+; count won't change.)
+;
+        push    ds
+        sub     ax,ax
+        mov     ds,ax
+        mov     ax,ds:[TIMER_COUNT+2]
+        mov     cs:[EndBIOSCountHigh],ax
+        mov     ax,ds:[TIMER_COUNT]
+        mov     cs:[EndBIOSCountLow],ax
+        pop     ds
+;
+; Read the timer count and save it.
+;
+        in      al,TIMER_0_8253         ;lsb
+        DELAY
+        mov     ah,al
+        in      al,TIMER_0_8253         ;msb
+        xchg    ah,al
+        neg     ax                      ;convert from countdown
+                                        ; remaining to elapsed
+                                        ; count
+        mov     cs:[EndTimedCount],ax
+;
+; Restart timer 0, which is still waiting for an initial count
+; to be loaded.
+;
+
+ife PS2
+
+        DELAY
+        mov     al,00110100b            ;mode 2, waiting to load a
+                                        ; 2-byte count
+        out     MODE_8253,al
+        DELAY
+        sub     al,al
+        out     TIMER_0_8253,al         ;lsb
+        DELAY
+        mov     al,ah
+        out     TIMER_0_8253,al         ;msb
+        DELAY
+
+endif
+
+        sti             ;let the BIOS count continue
+;
+; Time a zero-length code fragment, to get a reference for how
+; much overhead this routine has. Time it 16 times and average it,
+; for accuracy, rounding the result.
+;
+        mov     cs:[ReferenceCount],0
+        mov     cx,16
+        cli                             ;interrupts off to allow a
+                                        ; precise reference count
+RefLoop:
+        call    ReferenceZTimerOn
+        call    ReferenceZTimerOff
+        loop    RefLoop
+        sti
+        add     cs:[ReferenceCount],8   ;total + (0.5 * 16)
+        mov     cl,4
+        shr     cs:[ReferenceCount],cl  ;(total) / 16 + 0.5
+;
+; Restore the context of the program being timed and return to it.
+;
+        pop     cx
+        pop     ax
+        MPOPF
+        ret
+
+ZTimerOff endp
+
+;
+; Called by ZTimerOff to start the timer for overhead measurements.
+;
+
+ReferenceZTimerOn       proc    near
+;
+; Save the context of the program being timed.
+;
+        push    ax
+        pushf
+;
+; Set timer 0 of the 8253 to mode 2 (divide-by-N), to cause
+; linear counting rather than count-by-two counting.
+;
+        mov     al,00110100b    ;mode 2
+        out     MODE_8253,al
+;
+; Set the timer count to 0.
+;
+        DELAY
+        sub     al,al
+        out     TIMER_0_8253,al         ;lsb
+        DELAY
+        out     TIMER_0_8253,al         ;msb
+;
+; Restore the context of the program being timed and return to it.
+;
+        MPOPF
+        pop     ax
+        ret
+
+ReferenceZTimerOn       endp
+
+;
+; Called by ZTimerOff to stop the timer and add the result to
+; ReferenceCount for overhead measurements. Doesn't need to look
+; at the BIOS count because timing a zero-length code fragment
+; isn't going to take anywhere near 54 ms.
+;
+
+ReferenceZTimerOff proc near
+;
+; Save the context of the program being timed.
+;
+        pushf
+        push    ax
+        push    cx
+
+;
+; Match the interrupt-window delay in ZTimerOff.
+;
+        sti
+        rept    10
+        jmp     $+2
+        endm
+
+        mov     al,00000000b
+        out     MODE_8253,al            ;latch timer
+;
+; Read the count and save it.
+;
+        DELAY
+        in      al,TIMER_0_8253         ;lsb
+        DELAY
+        mov     ah,al
+        in      al,TIMER_0_8253         ;msb
+        xchg    ah,al
+        neg     ax                      ;convert from countdown
+                                        ; remaining to elapsed
+                                        ; count
+        add     cs:[ReferenceCount],ax
+;
+; Restore the context and return.
+;
+        pop     cx
+        pop     ax
+        MPOPF
+        ret
+
+ReferenceZTimerOff endp
+
+;********************************************************************
+;* Routine called to report timing results.                         *
+;********************************************************************
+
+ZTimerReport    proc    near
+
+        pushf
+        push    ax
+        push    bx
+        push    cx
+        push    dx
+        push    si
+        push    di
+        push    ds
+;
+        push    cs      ;DOS functions require that DS point
+        pop     ds      ; to text to be displayed on the screen
+        assume  ds:_TEXT
+;
+; See if midnight or more than an hour passed during timing. If so,
+; notify the user.
+;
+        mov     ax,[StartBIOSCountHigh]
+        cmp     ax,[EndBIOSCountHigh]
+        jz      CalcBIOSTime            ;hour count didn't change,
+                                        ; so everything's fine
+        inc     ax
+        cmp     ax,[EndBIOSCountHigh]
+        jnz     TestTooLong             ;midnight or two hour
+                                        ; boundaries passed, so the
+                                        ; results are no good
+        mov     ax,[EndBIOSCountLow]
+        cmp     ax,[StartBIOSCountLow]
+        jb      CalcBIOSTime            ;a single hour boundary
+                                        ; passed-that's OK, so long as
+                                        ; the total time wasn't more
+                                        ; than an hour
+
+;
+; Over an hour elapsed or midnight passed during timing, which
+; renders the results invalid. Notify the user. This misses the
+; case where a multiple of 24 hours has passed, but we'll rely
+; on the perspicacity of the user to detect that case.
+;
+TestTooLong:
+        mov     ah,9
+        mov     dx,offset TurnOverStr
+        int     21h
+        jmp     short ZTimerReportDone
+;
+; Convert the BIOS time to microseconds.
+;
+CalcBIOSTime:
+        mov     ax,[EndBIOSCountLow]
+        sub     ax,[StartBIOSCountLow]
+        mov     dx,54925                ;number of microseconds each
+                                        ; BIOS count represents
+        mul     dx
+        mov     bx,ax                   ;set aside BIOS count in
+        mov     cx,dx                   ; microseconds
+;
+; Convert timer count to microseconds.
+;
+        mov     ax,[EndTimedCount]
+        mov     si,8381
+        mul     si
+        mov     si,10000
+        div     si              ;* .8381 = * 8381 / 10000
+;
+; Add timer and BIOS counts together to get an overall time in
+; microseconds.
+;
+        add     bx,ax
+        adc     cx,0
+;
+; Subtract the timer overhead and save the result.
+;
+        mov     ax,[ReferenceCount]
+        mov     si,8381         ;convert the reference count
+        mul     si              ; to microseconds
+        mov     si,10000
+        div     si              ;* .8381 = * 8381 / 10000
+        sub     bx,ax
+        sbb     cx,0
+        mov     [CurrentCountLow],bx
+        mov     [CurrentCountHigh],cx
+;
+; Convert the result to an ASCII string by trial subtractions of
+; powers of 10.
+;
+        mov     di,offset PowersOfTenEnd - offset PowersOfTen - 4
+        mov     si,offset TimedCountStr
+CTSNextDigit:
+        mov     bl,'0'
+CTSLoop:
+        mov     ax,[CurrentCountLow]
+        mov     dx,[CurrentCountHigh]
+        sub     ax,PowersOfTen[di]
+        sbb     dx,PowersOfTen[di+2]
+        jc      CTSNextPowerDown
+        inc     bl
+        mov     [CurrentCountLow],ax
+        mov     [CurrentCountHigh],dx
+        jmp     CTSLoop
+CTSNextPowerDown:
+        mov     [si],bl
+        inc     si
+        sub     di,4
+        jns     CTSNextDigit
+;
+;
+; Print the results.
+;
+        mov     ah,9
+        mov     dx,offset OutputStr
+        int     21h
+;
+ZTimerReportDone:
+        pop     ds
+        pop     di
+        pop     si
+        pop     dx
+        pop     cx
+        pop     bx
+        pop     ax
+        MPOPF
+        ret
+
+ZTimerReport    endp
+
+        end
+
\ No newline at end of file
diff --git a/16/scrasm/LZTIMER.OBJ b/16/scrasm/LZTIMER.OBJ
new file mode 100644
index 0000000000000000000000000000000000000000..0511b4d5a24855619e478e21e5ac23c289a35415
GIT binary patch
literal 3231
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
JHR2C~^>0nZe=Yz3

literal 0
HcmV?d00001

diff --git a/16/scrasm/MAIN.ASM b/16/scrasm/MAIN.ASM
new file mode 100644
index 00000000..1c33a0fb
--- /dev/null
+++ b/16/scrasm/MAIN.ASM
@@ -0,0 +1,134 @@
+;;=======================================================================;;
+;;                                                                       ;;
+;; Scrolling Routines -- main program                                    ;;
+;;                                                                       ;;
+;; All other INC files are included here.  The main routines for the     ;;
+;; frame-by-frame execution loop are also here.  Finally I tried to keep ;;
+;; global variables stored in this file as well.                         ;;
+;;                                                                       ;;
+;;=======================================================================;;
+                dosseg
+                .model small
+                .386
+
+                .code
+                extrn   ZTimerOn:far, ZTimerOff:far, ZTimerReport:far
+
+INCLUDE constant.inc
+
+
+DW_TABLE        MACRO   inc,num
+                count = 0
+                number = 0
+                WHILE (count LT num)
+                        DW      number
+                        count = count + 1
+                        number = number + inc
+                        ENDM
+                ENDM
+
+DOSPRINT        MACRO   st
+                mov     ah,9
+                mov     dx,st
+                int     21h
+                ENDM
+
+EVEN
+Mult320         label   WORD
+MultBufWidth    label   WORD
+                DW_TABLE 320,200
+MultVirtWidth   label   WORD
+                DW_TABLE (VIRTUAL_WIDTH/4),200
+
+INCLUDE palette.inc
+INCLUDE keyb.inc
+INCLUDE modex.inc
+INCLUDE page.inc
+INCLUDE init.inc
+INCLUDE map.inc
+;INCLUDE sprite.inc NOT FOR NOW
+INCLUDE scroll.inc
+
+;; Various segments that need to be filled in later...
+EVEN
+segVideo        dw      0A000h          ; videoram segment
+segText         dw      0B800h          ; text segment
+segMap          dw      -1              ; Map info segment
+segTiles        dw      -1              ; Tile bitmap segment
+segBuffer       dw      -1              ; Local 320x200 buffer segment
+segCode         dw      -1              ; Code segment
+segPSP          dw      -1              ; PSP segment
+segPalette      dw      -1              ; Palette segment
+segTextPal      dw      -1              ; Saved text palette
+
+EVEN
+bDoTransition   db      0
+
+;; This routine is called for each frame.
+;; Right now it just scrolls, but later all sprite animation would
+;; occur here too.
+EVEN
+OneFrame        PROC    near
+                call    Scroll          ; Scrolls the screen
+;               call    AnimateSprites  ; prepares sprites on drawpage
+                jmp     FlipPage        ; shows drawpage...
+                ; no RET necessary
+OneFrame        ENDP
+
+;; Each frame -- call the frame motion code, then check for keyhit.
+EVEN
+MainLoop        PROC    NEAR
+next_frame:     call    OneFrame
+                JNKEY   next_frame
+                JKEYP   kESC,all_done   ; ESC -> quit, always
+                call    kprocCur
+                mov     al,bDoTransition
+                cmp     al,0
+                je      next_frame
+transition:     FLASH_OFF 16,segPalette
+                mov     bDoTransition,0
+                mov     ax,1
+                sub     ax,nMap
+                mov     nMap,ax         ; Flip maps
+
+                call    LoadData
+                call    update_full     ;<<<<
+                call    OneFrame
+                FLASH_ON 16,segPalette
+                jmp     next_frame
+all_done:       ret
+MainLoop        ENDP
+
+;; Beginning code -- Leaves text mode (saving the text screen) via
+;;                   a fade.  It loads the map data and draws one
+;;                   frame before it fades on.
+Beginning       PROC    near
+                NEW_PAL segTextPal
+                PAL_SAVE segTextPal
+                FADE_OFF 1,segTextPal
+                call    SaveVideo
+                MODEX_START             ; 320x200 Mode X graphics mode
+                PAL_BLACK
+
+                call    LoadData        ; This call will change...
+
+                call    update_full     ;<<<<
+                call    OneFrame
+                FADE_ON 1,segPalette
+                ret
+Beginning       ENDP
+
+;; Ending code -- restore to text mode via a flash
+Ending          PROC    near
+                FLASH_OFF 8,segPalette
+                call    RestoreVideo
+                FLASH_ON 8,segTextPal
+                ret
+Ending          ENDP
+
+                .data
+
+                .stack 2048
+
+                END Initialize
+
\ No newline at end of file
diff --git a/16/scrasm/MAIN.OBJ b/16/scrasm/MAIN.OBJ
new file mode 100644
index 0000000000000000000000000000000000000000..ff612818dd2a95532fff4a45d6d644adbf8a1b90
GIT binary patch
literal 18324
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

literal 0
HcmV?d00001

diff --git a/16/scrasm/MAKEFILE b/16/scrasm/MAKEFILE
new file mode 100644
index 00000000..8b9557ae
--- /dev/null
+++ b/16/scrasm/MAKEFILE
@@ -0,0 +1,47 @@
+OBJS=main.obj lztimer.obj
+INCLUDES=modex.inc keyb.inc palette.inc page.inc scroll.inc map.inc \
+         constant.inc init.inc
+PROGRAM=scroll
+
+.c.obj:
+   cl -c -Zi -Od -W4 $*.c
+
+.asm.obj:
+   masm -ml -zi $*.asm
+
+.obj.exe:
+   link /CO @$*.lnk
+
+project:  scroll.exe gensq.exe genmap.exe genpal.exe
+
+main.asm:  $(INCLUDES)
+
+scroll.lnk:  makefile
+   echo $(OBJS: =+)  > $*.lnk
+   echo $(PROGRAM); >> $*.lnk
+
+scroll.exe: $(OBJS) scroll.lnk
+   link /CO @$*.lnk
+
+gensq.obj: $*.c
+
+gensq.lnk: makefile
+   echo $*.obj; > $*.lnk
+
+gensq.exe: $*.obj $*.lnk
+
+genmap.obj: $*.c
+
+genmap.lnk: makefile
+   echo $*.obj; > $*.lnk
+
+genmap.exe: $*.obj $*.lnk
+
+genpal.obj: $*.c
+
+genpal.lnk: makefile
+   echo $*.obj; > $*.lnk
+
+genpal.exe: $*.obj $*.lnk
+
+
\ No newline at end of file
diff --git a/16/scrasm/MAP.INC b/16/scrasm/MAP.INC
new file mode 100644
index 00000000..c87494c2
--- /dev/null
+++ b/16/scrasm/MAP.INC
@@ -0,0 +1,413 @@
+;; MAP in own segment allows map of tiles to be up to 65536 tiles in area
+;; which translates to about 16.8 million pixels of virtual screen.  This
+;; can be represented in almost any rectangle -- just set MAP_WIDTH.
+
+;; Sorry this code isn't commented -- I was working on it right up until
+;; the point that I released this.  You have any questions?  Ask away
+;; (my internet address is in the DOC file).
+
+MAPHEADER       STRUCT, NONUNIQUE
+                MapName BYTE    ""
+                Wid     WORD    2
+                Ht      WORD    3
+                Extent  WORD    4
+                OffX1   WORD    5
+                OffY1   WORD    6
+                OffX2   WORD    7
+                OffY2   WORD    8
+                WrapX   WORD    9
+                WrapY   WORD    10
+                Magic   WORD    11
+MAPHEADER       ENDS
+MapInfo         MAPHEADER <>
+
+
+; In: DS:DX = offset of filename
+LoadMapFile     PROC    near
+                mov     ax,segMap
+                cmp     ax,-1
+                je      map_not_loaded
+                sub     ax,(SIZEOF MAPHEADER) / 16
+                mov     es,ax
+                mov     ah,49h
+                int     21h
+                mov     nError,ERR_MEM
+                jc      lm_err
+                mov     segMap,-1
+
+map_not_loaded: call    LoadFile
+                jc      lm_err
+
+                mov     ds,dx
+                mov     si,0
+                mov     ax,cs
+                mov     es,ax
+                lea     di,MapInfo
+                mov     cx,(SIZEOF MAPHEADER) / 4
+            rep movsd
+
+                add     dx,(SIZEOF MAPHEADER) / 16
+                mov     cs:segMap,dx
+
+                mov     BlankPage.Valid,0
+                mov     ShowPage.Valid,0
+                mov     DrawPage.Valid,0
+
+                mov     upper_left,0
+                mov     ScrollPosX,0
+                mov     ScrollPosY,0
+                mov     ScrollDX,0
+                mov     ScrollDY,0
+
+lm_err:         ret
+LoadMapFile     ENDP
+
+LoadTilesFile   PROC    near
+                mov     ax,segTiles
+                cmp     ax,-1
+                je      tiles_not_loaded
+                mov     es,ax
+                mov     ah,49h
+                int     21h
+                mov     nError,ERR_MEM
+                jc      lt_err
+                mov     segMap,-1
+
+tiles_not_loaded: call    LoadFile
+                jc      lm_err
+                mov     segTiles,dx
+
+                mov     BlankPage.Valid,0
+                mov     ShowPage.Valid,0
+                mov     DrawPage.Valid,0
+
+lt_err:         ret
+LoadTilesFile   ENDP
+
+EVEN
+LoadData        PROC    near
+        ; Load squares from data file
+                mov     bx,nMap
+                shl     bx,1
+                mov     dx,fntblTiles[bx]
+                mov     ds,segCode
+                call    LoadTilesFile
+                ; returns Carry if error
+                jc      load_error
+
+        ; Load map from data file
+                mov     ds,segCode
+                mov     bx,nMap
+                shl     bx,1
+                mov     dx,fntblMap[bx]
+                call    LoadMapFile
+                ; returns Carry if error
+
+load_error:     ret
+LoadData        ENDP
+
+EVEN
+update_full     PROC
+                mov     ds,segTiles
+                mov     es,segVideo
+                mov     fs,segMap
+
+                mov     dx,SC_INDEX
+                mov     al,MAP_MASK
+                out     dx,al
+
+                mov     di,DrawPage.Address
+                add     di,upper_left
+                mov     bp,MapInfo.OffX1
+                add     bp,MapInfo.OffY1
+
+                mov     dx,MapInfo.WrapX
+
+                mov     ch,(VIRTUAL_WIDTH/SQUARE_WIDTH)
+draw_full_loop: push    cx
+                push    si
+                push    dx
+
+                mov     al,11h
+                mov     si,0
+
+update_f_loop:  mov     dx,SC_INDEX + 1
+                out     dx,al
+                push    bp
+                call    draw_col
+                pop     bp
+                sub     di,(VIRTUAL_WIDTH * VIRTUAL_HEIGHT) / 4
+                add     si,(SQUARE_WIDTH * SQUARE_HEIGHT) / 4
+                shl     al,1
+                jnc     update_f_loop
+
+                pop     dx
+                dec     dx
+                jnz     update_f_go_on
+                mov     dx,MapInfo.Wid
+                sub     bp,dx
+update_f_go_on: inc     bp
+                pop     si
+                add     di,(SQUARE_WIDTH/ 4)
+                pop     cx
+                dec     ch
+                jnz     draw_full_loop
+
+
+
+
+
+
+
+
+
+
+
+                mov     dx,GC_INDEX
+                mov     ax,ALL_COPY_BITS
+                out     dx,ax
+
+                mov     dx,SC_INDEX
+                mov     ax,0F02h
+                out     dx,ax
+
+                mov     ds,segVideo
+                mov     si,DrawPage.Address
+                add     si,upper_left
+                mov     es,segVideo
+                mov     di,BlankPage.Address
+                add     di,upper_left
+                mov     cx,(VIRTUAL_WIDTH * VIRTUAL_HEIGHT) / 4
+            rep movsb
+                mov     si,DrawPage.Address
+                add     si,upper_left
+                mov     di,ShowPage.Address
+                add     di,upper_left
+                mov     cx,(VIRTUAL_WIDTH * VIRTUAL_HEIGHT) / 4
+            rep movsb
+
+                mov     dx,GC_INDEX
+                mov     ax,ALL_DRAW_BITS
+                out     dx,ax
+
+                ret
+update_full     ENDP
+
+EVEN
+update_left     PROC
+                mov     ds,cs:segTiles
+                mov     es,cs:segVideo
+                mov     fs,cs:segMap
+
+                mov     dx,SC_INDEX
+                mov     al,MAP_MASK
+                out     dx,al
+
+                mov     al,011h
+                mov     si,0
+                mov     di,cs:DrawPage.Address
+                add     di,cs:upper_left        ; becomes DI later
+                mov     bp,MapInfo.OffX1
+                add     bp,MapInfo.OffY1
+
+update_l_loop:  mov     dx,SC_INDEX + 1
+                out     dx,al
+                push    bp
+                call    draw_col
+                pop     bp
+                sub     di,(VIRTUAL_WIDTH * VIRTUAL_HEIGHT) / 4
+                add     si,(SQUARE_WIDTH * SQUARE_HEIGHT) / 4
+                shl     al,1
+                jnc     update_l_loop
+
+                ret
+update_left     ENDP
+
+EVEN
+update_right    PROC    near
+                mov     ds,cs:segTiles
+                mov     es,cs:segVideo
+                mov     fs,cs:segMap
+
+                mov     dx,SC_INDEX
+                mov     al,MAP_MASK
+                out     dx,al
+
+                mov     bp,MapInfo.OffX2
+                add     bp,MapInfo.OffY1
+
+                mov     al,011h
+                mov     si,0
+
+                mov     di,cs:DrawPage.Address  ; becomes DI
+                add     di,cs:upper_left
+                add     di,(VIRTUAL_WIDTH - SQUARE_WIDTH) / 4
+
+update_r_loop:  mov     dx,SC_INDEX + 1
+                out     dx,al
+
+                push    bp
+                call    draw_col
+                pop     bp
+                sub     di,(VIRTUAL_WIDTH * VIRTUAL_HEIGHT) / 4
+                add     si,(SQUARE_WIDTH * SQUARE_HEIGHT) / 4
+                shl     al,1
+                jnc     update_r_loop
+
+                ret
+update_right    ENDP
+
+EVEN
+update_top      PROC
+                mov     ds,cs:segTiles
+                mov     es,cs:segVideo
+                mov     fs,cs:segMap
+
+                mov     dx,SC_INDEX
+                mov     al,MAP_MASK
+                out     dx,al
+
+                mov     di,cs:DrawPage.Address
+                add     di,cs:upper_left
+                mov     bp,MapInfo.OffX1
+                add     bp,MapInfo.OffY1
+
+                mov     al,011h
+                mov     si,0
+
+update_top_loop:
+                mov     dx,SC_INDEX + 1
+                out     dx,al
+                push    bp
+                call    draw_row
+                pop     bp
+                sub     di,VIRTUAL_WIDTH / 4
+                add     si,(SQUARE_WIDTH * SQUARE_HEIGHT) / 4
+                shl     al,1
+                jnc     update_top_loop
+
+                ret
+update_top      ENDP
+
+EVEN
+update_bottom   PROC
+                mov     ds,cs:segTiles
+                mov     es,cs:segVideo
+                mov     fs,cs:segMap
+
+                mov     dx,SC_INDEX
+                mov     al,MAP_MASK
+                out     dx,al
+
+                mov     di,cs:DrawPage.Address
+                add     di,cs:upper_left
+                add     di,(VIRTUAL_WIDTH * (VIRTUAL_HEIGHT - SQUARE_HEIGHT)) / 4
+                mov     bp,MapInfo.OffX1
+                add     bp,MapInfo.OffY2
+
+                mov     al,011h
+                mov     si,0
+
+update_bottom_loop:
+                mov     dx,SC_INDEX + 1
+                out     dx,al
+                push    bp
+                call    draw_row
+                pop     bp
+                sub     di,VIRTUAL_WIDTH / 4
+                add     si,(SQUARE_WIDTH * SQUARE_HEIGHT) / 4
+                shl     al,1
+                jnc     update_bottom_loop
+
+                ret
+update_bottom   ENDP
+
+; Draws ONE plane of a single col
+EVEN
+draw_col        PROC    near
+        ; DI->upper left corner of col to draw
+        ; BP->col of map to draw
+        ; SI used to point at tiles
+        ; AX,CX used
+        ; BX used to push SI
+        ; DX unused
+                shl     eax,16  ; save it
+                mov     ax,MapInfo.WrapY
+
+                mov     cl,(VIRTUAL_HEIGHT / SQUARE_HEIGHT)
+do_col_loop:    mov     bx,si
+                mov     bh,byte ptr fs:[bp]     ; change tile #
+
+                mov     ch,SQUARE_HEIGHT
+do_col_sq_loop: mov     dl,byte ptr ds:[bx+2]
+                mov     dh,byte ptr ds:[bx+3]
+                shl     edx,16
+                mov     dl,byte ptr ds:[bx+0]
+                mov     dh,byte ptr ds:[bx+1]
+                mov     es:[di],edx     ; 32-bit write
+                add     di,VIRTUAL_WIDTH / 4
+                add     bx,4
+                dec     ch
+                jnz     do_col_sq_loop
+
+                add     bp,MapInfo.Wid
+                dec     ax
+                jnz     yayaya
+                mov     ax,MapInfo.Ht
+                sub     bp,MapInfo.Extent
+yayaya:
+
+                dec     cl
+                jnz     do_col_loop
+
+                shr     eax,16  ; restore it
+
+                ret
+draw_col        ENDP
+
+; Draws ONE plane of a single row
+EVEN
+draw_row        PROC    near
+                push    ax
+;               shl     eax,16  ; save ax
+
+                mov     ax,MapInfo.WrapX
+
+        ; DI->upper left corner of row to draw
+        ; BP->row of map to draw
+        ; SI used to point at tiles
+        ; AX,CX used
+        ; BX used to push SI
+        ; DX unused
+
+                mov     cl,(VIRTUAL_WIDTH / SQUARE_WIDTH)
+do_row_loop:    mov     bx,si
+                mov     bh,byte ptr fs:[bp]     ; change tile #
+
+                mov     ch,SQUARE_HEIGHT
+do_row_sq_loop: mov     dl,byte ptr ds:[bx+2]
+                mov     dh,byte ptr ds:[bx+3]
+                shl     edx,16
+                mov     dl,byte ptr ds:[bx+0]
+                mov     dh,byte ptr ds:[bx+1]
+                mov     es:[di],edx
+                add     di,(VIRTUAL_WIDTH / 4)
+                add     bx,4
+                dec     ch
+                jnz     do_row_sq_loop
+
+                add     di,(-VIRTUAL_WIDTH*SQUARE_HEIGHT + SQUARE_WIDTH) / 4
+                inc     bp
+                dec     ax
+                jnz     yayaya2
+                mov     ax,MapInfo.Wid
+                sub     bp,ax
+yayaya2:
+                dec     cl
+                jnz     do_row_loop
+
+;               shr     eax,16  ; restore it
+                pop     ax
+                ret
+draw_row        ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/MODEX.INC b/16/scrasm/MODEX.INC
new file mode 100644
index 00000000..174aa354
--- /dev/null
+++ b/16/scrasm/MODEX.INC
@@ -0,0 +1,88 @@
+; ====================================================================
+; Entry points:
+; ====================================================================
+MODEX_START     MACRO
+                mov     ax,13h  ;let the BIOS set standard 256-color
+                int     10h     ; mode (320x200 linear)
+;               PALETTE_BLACK
+                call    ModifyForX
+                ENDM
+
+; ====================================================================
+; This is MODE-X code from Dr. Dobb's Journal, by Michael Abrash.
+; I modified it from 320x240 back to 320x200, and then to 512 virtual
+; width, for scrolling purposes.
+; ====================================================================
+
+; Mode X (320x240, 256 colors) mode set routine. Works on all VGAs.
+; ****************************************************************
+; * Revised 6/19/91 to select correct clock; fixes vertical roll *
+; * problems on fixed-frequency (IBM 851X-type) monitors.        *
+; ****************************************************************
+; Modified from public-domain mode set code by John Bridges.
+
+; Index/data pairs for CRT Controller registers that differ between
+; mode 13h and mode X.
+CRTParms label  word
+;       dw      00d06h  ;vertical total
+;       dw      03e07h  ;overflow (bit 8 of vertical counts)
+;       dw      04109h  ;cell height (2 to double-scan)
+;       dw      0ea10h  ;v sync start
+;       dw      0ac11h  ;v sync end and protect cr0-cr7
+;       dw      0df12h  ;vertical displayed = 480
+        dw      00014h  ;turn off dword mode                    *
+;       dw      0e715h  ;v blank start
+;       dw      00616h  ;v blank end
+        dw      0e317h  ;turn on byte mode                      *
+
+        dw      (VIRTUAL_WIDTH*32)+13h  ; width of screen = VWid   NEW
+;       dw      09012h  ;vertical displayed = 400 (already like this)
+CRT_PARM_LENGTH equ     (($-CRTParms)/2)
+
+ModifyForX      PROC    near
+                mov     dx,SC_INDEX
+                mov     ax,0604h
+                out     dx,ax           ;disable chain4 mode
+                mov     ax,0100h
+                out     dx,ax           ;synchronous reset while setting Misc
+                                        ; Output for safety, even though clock
+                                        ; unchanged
+                mov     dx,MISC_OUTPUT
+                mov     al,0e3h
+                out     dx,al           ;select 25 MHz dot clock & 60 Hz scanning rate
+
+                mov     dx,SC_INDEX
+                mov     ax,0300h
+                out     dx,ax           ;undo reset (restart sequencer)
+
+                mov     dx,CRTC_INDEX   ;reprogram the CRT Controller
+                mov     al,11h          ;VSync End reg contains register write
+                out     dx,al           ; protect bit
+                inc     dx              ;CRT Controller Data register
+                in      al,dx           ;get current VSync End register setting
+                and     al,7fh          ;remove write protect on various
+                out     dx,al           ; CRTC registers
+                dec     dx              ;CRT Controller Index
+                cld
+                push    cs
+                pop     ds
+                mov     si,offset CRTParms ;point to CRT parameter table
+                mov     cx,CRT_PARM_LENGTH ;# of table entries
+SetCRTParmsLoop:
+                lodsw                   ;get the next CRT Index/Data pair
+                out     dx,ax           ;set the next CRT Index/Data pair
+                loop    SetCRTParmsLoop
+
+                mov     dx,SC_INDEX
+                mov     ax,0f02h
+                out     dx,ax           ;enable writes to all four planes
+                mov     ax,SCREEN_SEG   ;now clear all display memory, 8 pixels
+                mov     es,ax           ; at a time
+                sub     di,di           ;point ES:DI to display memory
+                sub     ax,ax           ;clear to zero-value pixels
+                mov     cx,8000h        ;# of words in display memory
+            rep stosw                   ;clear all of display memory
+
+                ret
+ModifyForX      ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/PAGE.INC b/16/scrasm/PAGE.INC
new file mode 100644
index 00000000..a55bdf0b
--- /dev/null
+++ b/16/scrasm/PAGE.INC
@@ -0,0 +1,109 @@
+;; ====================================================================
+;; (Code follows)
+;; ====================================================================
+
+EVEN
+upper_left      dw      0               ; Stores upper left corner offset
+                                        ; relative to page offset.
+pages           dw      0               ; for counting frame-per-sec
+
+PAGE_INFO       STRUCT 2,NONUNIQUE
+                Address         dw      0
+                UpperLeftAddress dw     0
+                MapPosX         dw      0
+                MapPosY         dw      0
+                Alignment       db      0
+                AlignmentMask   db      0
+                ScrollOffset    dw      0
+                Rectangles      dw      0
+                Valid           db      0
+PAGE_INFO       ENDS
+
+DrawPage        PAGE_INFO <PAGE_0,PAGE_0>
+ShowPage        PAGE_INFO <PAGE_1,PAGE_1>
+BlankPage       PAGE_INFO <PAGE_2,PAGE_2>
+
+ROTATE3         MACRO   reg,item
+                mov     reg,cs:ShowPage.item
+                xchg    reg,cs:BlankPage.item
+                xchg    reg,cs:DrawPage.item
+                mov     cs:ShowPage.item,reg
+                ENDM    ; Leaves ShowPage.item in reg!
+
+;; This procedure is used to flip between the three available pages.
+;; Originally from Dr. Dobb's Journal's Graphics Programming column by
+;; Michael Abrash, I've reworked the code to be more specific to my
+;; own purposes, and commented it more.
+EVEN
+FlipPage        PROC    near
+        ; This series of instructions circles the show_page, blank_page,
+        ; and draw page appropriately and leaves the current page to show
+        ; in AX.  Note that it's a lot more instructions than it looks like,
+        ; but I unrolled the copy loop for speed.  So-so good idea, because
+        ; if you add a field and forget to rotate it, it could mean trouble!
+                ROTATE3 ax,Rectangles
+                ROTATE3 ax,ScrollOffset
+                ROTATE3 ax,MapPosX
+                ROTATE3 ax,MapPosY
+;               ROTATE3 al,AlignmentMask        SPRITES ...
+                ROTATE3 al,Alignment
+                mov     di,ax           ; DI = scroll offset low, and
+                                        ; garbage in the high bits...
+                and     di,3            ; DI = pixel pan, 0 to 3.
+                shl     di,1            ; Mode X requires 0 2 4 or 6.
+                ROTATE3 ax,Address
+                ROTATE3 al,Valid
+                ROTATE3 ax,UpperLeftAddress ; Leaves AX=ShowPage.ULAddr
+
+                add     ax,cs:ShowPage.ScrollOffset
+
+        ; AX is set up to be the current show page already.
+        ; By pre-loading BX with the low-address set code, and CX with
+        ; the high-address set code, we can more quickly flip the page
+        ; after the vertical retrace period.
+                mov     bl,START_ADDRESS_LOW    ;preload for fastest
+                mov     bh,al                   ; flipping once display
+                mov     cl,START_ADDRESS_HIGH   ; enable is detected
+                mov     ch,ah
+
+        ; Wait for display enable to be active (status is active low), to be
+        ; sure both halves of the start address will take in the same frame.
+                mov     dx,INPUT_STATUS_1
+WaitDE:         in      al,dx
+                test    al,01h
+                jnz     WaitDE  ;display enable is active low (0 = active)
+
+        ; Set the start offset in display memory of the page to display.
+                mov     dx,CRTC_INDEX
+                mov     ax,bx
+                out     dx,ax   ;start address low
+                mov     ax,cx
+                out     dx,ax   ;start address high
+
+        ; Now wait for vertical sync, so the other page will be invisible when
+        ; we start drawing to it.
+                mov     dx,INPUT_STATUS_1
+WaitVS:         in      al,dx
+                test    al,08h
+                jz      WaitVS  ;vertical sync is active high (1 = active)
+
+        ; Finally, have to adjust the pixel panning register in order
+        ; to fine-tune the starting address on a pixel level.
+        ; This pixel pan value is the scroll offset mod 4 -- but since
+        ; Mode X's pixel pan works by values of 2 (0, 2, 4 or 6) we
+        ; have to shift appropriately.
+                mov     dx,ATC_INDEX
+                mov     al,13h  ; 13h = set pixel pan
+                out     dx,al
+                mov     ax,di   ; DI = pixel pan calculated above
+                out     dx,al
+                mov     dx,ATC_INDEX
+                mov     al,32   ; Allows the computer to use this register
+                out     dx,al   ; again.  Without this OUT, the screen will
+                                ; remain blank!
+
+        ; Increment the page counter now!
+                inc     cs:pages
+                ret
+FlipPage        ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/PALETTE.INC b/16/scrasm/PALETTE.INC
new file mode 100644
index 00000000..e3bd381e
--- /dev/null
+++ b/16/scrasm/PALETTE.INC
@@ -0,0 +1,239 @@
+;; Palette operations
+;; Note that where needed in the macros, a "palette" refers to
+;; the segment handle to a 768-byte piece of memory.  So palettes
+;; can be loaded and freed, they're not permanent, but if you want
+;; to use a fixed (not allocated) palette you'd better make sure
+;; it's segment aligned or else you can't use these macros.  If it
+;; is, you can just supply "seg myPalette" as the 'palette' argument
+;; to any of these macros.
+
+;; Fade from a palette to black
+FADE_OFF        MACRO   fade,palette
+                mov     si,0
+                mov     ds,palette
+                mov     bh,fade         ; positive -> Gets dimmer...
+                mov     bl,0            ; Starts exact
+                mov     cx,64/fade+1    ; Total number of loops required
+                call    FadePalette
+                ENDM
+
+;; Fade from black to a palette
+FADE_ON         MACRO   fade,palette
+                mov     si,0
+                mov     ds,palette
+                mov     bh,-fade        ; negative -> Gets brighter...
+                mov     bl,64           ; Starts totally dimmed
+                mov     cx,64/fade+1    ; Total number of loops required
+                call    FadePalette
+                ENDM
+
+;; Flash from a palette to white
+FLASH_OFF       MACRO   fade,palette
+                mov     si,0
+                mov     ds,palette
+                mov     bh,-fade        ; negative -> gets brighter
+                mov     bl,0            ; Starts exact
+                mov     cx,64/fade+1    ; Total number of loops required
+                call    FadePalette
+                ENDM
+
+;; Flash from white to a palette
+FLASH_ON        MACRO   fade,palette
+                mov     si,0
+                mov     ds,palette
+                mov     bh,fade         ; positive -> Gets dimmer...
+                mov     bl,-64          ; Starts totally bright
+                mov     cx,64/fade+1    ; Total number of loops required
+                call    FadePalette
+                ENDM
+
+;; Save a palette into a palette-sized piece of memory
+PAL_SAVE        MACRO   palette
+                mov     es,palette
+                mov     di,0
+                call    SavePalette
+                ENDM
+
+; Returns AX = a new segment for a palette
+NEW_PAL         MACRO   palette
+                mov     bx,(256 * 3) / 16
+                mov     ah,48h
+                int     21h
+                mov     palette,ax
+                ENDM
+
+;; Black the entire palette temporarily.  Used to blank the screen while
+;; drawing a frame before fading in.
+PAL_BLACK       MACRO
+                mov     ax,seg tmppal
+                mov     ds,ax
+                mov     si,OFFSET tmppal
+                mov     bh,-1           ; Doesn't really matter...
+                mov     bl,64           ; Starts totally dimmed
+                mov     cx,1            ; Just one time -- to leave it black
+                call    FadePalette
+                ENDM
+
+;; drawing a frame before fading in.
+PAL_WHITE       MACRO
+                mov     ax,seg tmppal
+                mov     ds,ax
+                mov     si,OFFSET tmppal
+                mov     bh,-1           ; Doesn't really matter...
+                mov     bl,-64          ; Starts totally dimmed
+                mov     cx,1            ; Just one time -- to leave it black
+                call    FadePalette
+                ENDM
+
+;; Black the entire palette temporarily.  Used to blank the screen while
+;; drawing a frame before fading in.
+PAL_UPDATE      MACRO
+                mov     cx,0            ; 0 times = update
+                call    FadePalette
+                ENDM
+
+WAITBORDER      MACRO
+                LOCAL   wbr1,wbr2
+                mov     dx,INPUT_STATUS_1
+wbr1:           in      al,dx
+                test    al,8
+                jnz     wbr1
+wbr2:           in      al,dx
+                test    al,8
+                jz      wbr2
+                ENDM
+
+;; Fade Palette:
+;; The following code is modified greatly from the Future Crew's palette
+;; fading code.  Works on blocks of 256 colors only, so far, but I might
+;; change it later.  Also, it theoretically could "anti-fade" -- fade to
+;; white -- which I call flashing, so I added that ability, which was
+;; missing from FC's code.
+EVEN
+tmppal          DB      768 dup (?)      ; Stores old palette
+FadePalette     PROC NEAR
+                mov     ax,seg tmppal
+                mov     es,ax
+
+FadeLoop:       push    cx
+                push    si
+
+                cmp     cx,0
+                je      JustUpdate
+
+        ; Load in the colors in the palette
+                mov     di,OFFSET tmppal ; ES:DI -> temp palette
+                mov     cx,768          ; Reads 256*3 bytes at a time.
+loadpal_loop:   mov     al,ds:[si]      ; Load one color byte
+                inc     si
+                sub     al,bl           ; Subtract the fade amount
+                jge     pal_more        ; Limit the range by clipping
+                xor     al,al           ;  to between 0 and 63
+                jmp     pal_ok          ; (there's probably a faster
+pal_more:       cmp     al,63           ; way to do it than this,
+                jle     pal_ok          ; but I don't know it)
+                mov     al,63
+pal_ok:         mov     es:[di],al      ; Store that byte in the new
+                inc     di
+                dec     cx              ;  temp palette and loop.
+                jnz     loadpal_loop
+
+        ; Get ready to move this block of palette values
+JustUpdate:     sti                     ; Let interrupts happen now,
+                WAITBORDER              ;  while waiting for a retrace,
+                cli                     ;  instead of more critical times
+
+                mov     dx,PEL_WRITE_REG; Set up to write to color register,
+                xor     al,al           ; starting at palette entry 0.
+                out     dx,al
+                mov     dx,PEL_DATA_REG ; Point at color port
+
+        ; Quickly put out the first half of the color palette
+                mov     di,OFFSET tmppal
+                mov     cl,(768/6)/2    ; Does 2 loops of 128 colors each.
+                cli                     ;  Waits a retrace inbetween...
+FirstHalfLoop:  REPEAT 6                ; Steps of 6 -- reduces the
+                mov     al,es:[di]      ; number of LOOP instructions
+                inc     di
+                out     dx,al
+                ENDM
+                dec     cl
+                jnz     FirstHalfLoop
+                sti
+
+                WAITBORDER              ; Waits one retrace -- less flicker
+                mov     dx,PEL_DATA_REG ; Reset DX
+
+        ; Now, quickly put out the other half of the colors.
+                mov     cl,(768/6)/2
+                cli
+SecondHalfLoop: REPEAT 6                ; Steps of 6 -- reduces the
+                mov     al,es:[di]      ; number of LOOP instructions
+                inc     di
+                out     dx,al
+                ENDM
+                dec     cl
+                jnz     SecondHalfLoop
+
+        ; For the next iteration, restore everything and loop
+                pop     si
+                pop     cx
+
+                cmp     cx,0
+                je      JustUpdated
+
+                add     bl,bh           ; Change brightness by BH
+
+                dec     cx
+                jnz     FadeLoop
+
+        ; All done, re-enable interrupts and return
+JustUpdated:    sti
+                ret
+FadePalette     ENDP
+
+;; Saves the palette into the memory pointed at by DS:SI.  That memory
+;; must be at least 768 bytes long...
+SavePalette     PROC NEAR
+                mov     dx,PEL_READ_REG ; Set up to read from color register,
+                xor     al,al           ; starting at palette entry 0.
+                out     dx,al
+                mov     dx,PEL_DATA_REG
+
+        ; Quickly read in the first half of the color palette
+                mov     cl,(768/6)
+                cli
+ReadPalLoop:    REPEAT 6                ; Steps of 6 -- reduces the
+                in      al,dx           ; number of LOOP instructions
+                mov     es:[di],al
+                inc     di
+                ENDM
+                dec     cl
+                jnz     ReadPalLoop
+        ; All done, re-enable interrupts and return
+                sti
+                ret
+SavePalette     ENDP
+
+;; Load a palette from a file.  Opens the file and reads it into
+;; memory (standard LoadFile) and then points the palette at that
+;; newly allocated memory.  Also, frees old memory before it does
+;; any loading ...
+LoadPaletteFile PROC    near
+                mov     ax,segPalette
+                cmp     ax,-1
+                je      pal_not_loaded
+                mov     es,ax
+                mov     ah,49h
+                int     21h
+                mov     nError,ERR_MEM
+                jc      lp_err
+                mov     segPalette,-1
+
+pal_not_loaded: call    LoadFile
+                jc      lp_err
+
+                mov     segPalette,dx
+lp_err:         ret
+LoadPaletteFile ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/SCROLL.DOC b/16/scrasm/SCROLL.DOC
new file mode 100644
index 00000000..0893db36
--- /dev/null
+++ b/16/scrasm/SCROLL.DOC
@@ -0,0 +1,297 @@
+            ________________________________________________
+           |+----------------------------------------------+|
+           ||          I N T R O D U C I N G :             ||
+           |+----------------------------------------------+|
+           ||               Steve's 4-Way                  ||
+           ||    ___    ___   ____     ___    _      _     ||
+           ||   / __|  / __| |  _ \   / _ \  | |    | |    ||
+           ||  | <_   | |    | |_> | | | | | | |    | |    ||
+           ||   \_ \  | |    |    /  | | | | | |    | |    ||
+           ||   __> | | |__  | |\ \  | |_| | | |__  | |__  ||
+           ||  |___/   \___| |_| \_|  \___/  |____| |____| ||
+           |+______________________________________________+|
+           +------------------------------------------------+
+
+  There, now that I have the hype outta the way, let me explain what
+this program is.  I'm releasing the source code to my 4-way scrolling
+code so that others can learn from it.  There aren't enough really
+good resources out there for someone learning to program games, so I'm
+trying to do my part to help.
+
+WHAT IT IS:
+
+  The code is 100% assembly, for which I use MASM 6.0, so there may
+be a few problems converting to Turbo Assembler.  I also use the ".386"
+directive, meaning that you can't run this code with a 286 or earlier.
+But most of the code should be easily convertible.  I haven't been
+programming for 386's much so I really don't make the use of the 386
+registers like I could have.  Mostly I just did it for some extra 386
+instructions.
+
+  You'll need a VGA which can support mode 13h, the MCGA mode.  This
+code runs in "tweaked" MCGA mode, or what is called "Mode X".  For more
+information on Mode X, check out the 1991 - 1992 issues of Doctor Dobbs
+Journal, wherein you will find Michael Abrash's excellent Graphics
+Programming column.  This is where I (and many others) found out about
+Mode X, which is an excellent graphics mode for fast 256-color graphics.
+Also, you can take a look at XLIB, YakIcons, FastGraph, etc which are all
+graphics libraries (public domain or otherwise) which support Mode X
+graphics and probably have some good documentation on programming the mode.
+Additionally, check out _The Programmer's Guide to the EGA and VGA Cards_,
+by Richard Ferraro, and _Power Graphics Programming_ (out of print, but
+available directly from Que Books) by Michael Abrash.  Finally, you can
+ask about graphics programming on many newsgroups such as
+"rec.games.programmer"...
+
+WHAT IT DOES:
+
+  The code will allow you to create "tiled" background patterns and then
+to omnidirectionally scroll over them.  You could implement sprite routines
+and then animate them over the background, but I haven't gotten this far
+yet.  The scrolling is always relational -- ie no "jump-to"'s, just "scroll
+left", "scroll up", etc.  Jump to would be very easy to implement, I just
+haven't done it yet.
+
+  It runs at about 60-70 fps on a 386/20, which means that it is operating
+in under the time of one vertical refresh (_just_ under, according to some
+timing I've done).  This could probably be reduced, but the best way to
+reduce it is to limit the speed at which it scrolls -- if you stick to
+scrolling at most 8 pixels at a time in two axes or 16 pixels at a time
+in one axis, it is very fast.  More than that, and it occasionally takes
+more than one refresh period even on my 486.  Still, that should be
+fast enough for just about any game.
+
+  I also included some routines to generate maps, tiles, and palettes
+so you can see the file formats.  These are in C, and the executables
+are around in case you don't care to recompile.  None of the utilities
+are exactly production quality.  You'll have to look at the code to
+figure out the arguments!  Luckily you can just run them with no args
+and they perform default behavior.
+
+  Lastly, the program SCROLL.EXE is a demo of what it can do.  In this
+demo you can use one of two sets of keyboard controls to scroll around.
+One, the default set of commands, lets you press up/down/left/right and
+scroll in that direction.  The other has "intertia" -- pressing up/down
+left/right will accelerate you in that direction.  You'll see what I
+mean, just experiment.  You can switch keyhandlers by pressing K.
+You can also switch between the diagonal pattern map and a logo map
+by pressing M.  (By the way, it will eventually run out of memory loading
+the maps and the diagonal map will screw up... don't worry about it,
+it'd be fixed if I had more time).  Try it out.
+
+CREDIT WHERE CREDIT IS DUE:
+
+  People who (unknowingly) helped me out:
+
+        Keyboard by Steven Dollins, Brown Computer Group.  From his
+                KEYINT routines, which is an INT 9 handler to let you
+                keep track of many keys being pressed at the same time.
+        Graphics, basically, by Michael Abrash, whose Mode X columns
+                influenced me greatly.
+        Palette fades and file I/O by the Future Crew.  Thanks for
+                letting out the Mental Surgery code!
+        CPU detection by Ray Duncan, taken from one of his books.
+
+  Obviously I haven't just pirated the code, it's all from publicly
+released source code and I modified it a bit.  But I wouldn't have come
+up with this whole thing without those helping hands.  Thanks.
+
+HOW IT WORKS:
+
+  Here's how the scrolling works.  I'll explain it from a single-page
+point of view, although it actually uses several pages of video memory.
+The video memory is laid out like this:
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍ» ÄÄÄ
+º                                ³ /  /  /  / º  ³
+º                                ³/  /  /  /  º  ³
+º                                ³  /  /  /  /º  ³
+º           Visible page         ³ / Not /  / º  ³
+º                                ³/ visible/  º  ³
+º                                ³  /  /  /  /º 64K
+º                                ³ /  /  /  / º  ³
+ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ/  /  /  /  º  ³
+º  /  /  /  /  /  /  /  /  /  /  /  /  /  /  /º  ³
+º /  /  /  /  /  /  /  /  /  /  /  /  /  /  / º  ³
+º/  /  /  /  /  /  /  /  /  /  /  /  /  /  /  º  ³
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ
+In other words, it has a virtual width greater than the actual screen
+width, and a virtual height higher than the actual screen height.  The
+VGA hardware allows hardware panning around within the virtual area, so
+that makes panning much easier:  you only have to draw the information
+that is coming on to the screen with each pan.
+
+What is Happening:      What the user sees:
+ÉÍÍÍÍÍÍÍÍÑÍÍÍÍ»          ÚÄÄÄÄÄÄÄÄ¿
+º     hel³////º          ³     hel³           The picture that is
+ÇÄÄÄÄÄÄÄÄÙ////º          ÀÄÄÄÄÄÄÄÄÙ           coming on to the screen
+º/////////////º                               ("hello") appears to
+ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ                               the user to be scrolling
+ÉÍÑÍÍÍÍÍÍÍÑÍÍÍ»          ÚÄÄÄÄÄÄÄÄ¿           left, although it is
+º/³   hell³///º          ³    hell³           actually at a stationary
+º/ÀÄÄÄÄÄÄÄÙ///º          ÀÄÄÄÄÄÄÄÄÙ           location in memory...
+º/////////////º                               Each time the frame moves,
+ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ                               it is not necessary to
+ÉÍÍÑÍÍÍÍÍÍÍÑÍÍ»          ÚÄÄÄÄÄÄÄÄ¿           redraw the parts that stay
+º//³  hello³//º          ³   hello³           on the screen, just the
+º//ÀÄÄÄÄÄÄÄÙ//º          ÀÄÄÄÄÄÄÄÄÙ           parts that become visible.
+º/////////////º
+ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ
+
+  The same works up&down too, or even left/right and up/down at the same
+time.  The problem occurs when you scroll enough to hit the edge of the
+virtual space.  Luckily, video memory increases and wraps at the right
+edge to one line down on the left edge.  So you end up with a situation
+like this after scrolling too far right:
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍ» ÄÄÄ
+ÇÄÄÄÄÄÄÄ¿//////³    º  ³        User sees:
+º       ³//////³  Thº  ³       ÚÄÄÄÄÄÄÄÄÄÄÄ¿
+ºe quick³//////³    º 64K      ³           ³
+º       ³//////ÀÄÄÄĶ  ³       ³  The quick³
+ÇÄÄÄÄÄÄÄÙ///////////º  ³       ³           ³
+º///////////////////º  ³       ÀÄÄÄÄÄÄÄÄÄÄÄÙ
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ
+The wrapping is transparent to the user.  So, it appears that you can
+scroll left & right infinitely, by simply always updating the amount of
+memory that has scrolled into view.
+
+  But what happens when you scroll too far down?  Now Intel segments come
+to the rescue!  Because the video memory is 64K, and that is also the
+largest amount of memory you can access in a segment, the segment arithmetic
+performs the top-to-bottom wrapping for me.  It results in a similar
+situation as is pictured above, but with the screen split horizontally
+instead of vertically.  Again, it's completely transparent to the user.
+
+  One performance optimization that I've done is to organize the background
+picture that is being scrolled into quantitized "tiles" -- 16x16 pixels in
+area.  This means that you can store a large amount of picture data if that
+data is repetitive -- as the backgrounds of many video games are.  This also
+helps when figuring out how much new stuff to draw on the screen.  I can wait
+until the panning crosses a 16-pixel border, then draw another 16-pixel
+strip, and then wait for another tile crossing, etc.  You can see this in
+the MAP.INC and SCROLL.INC code.  16x16 pixels also leads to 256-pixel-square
+tiles, which is always a convenient number in assembly... it helps out in
+several places in the code.
+
+  So, the display page is "wandering" around the video memory, only drawing
+what is necessary at any time.  Meanwhile you can animate sprites over the
+background, etc.  The only problem is that with one page, information is
+constantly being drawn to that page and you can never guarantee that it is in
+a correct state at the time of a vertical refresh period.  Instead, I actually
+use several pages, so that one can be shown while the other is worked on.
+This guarantees a perfect picture at any time.  So for now, let's ignore the
+scrolling for a second, and talk about the paging, because it's easier to
+understand the paging if scrolling isn't happening.
+
+  Here's a basic explanation of how the paging works.  I use three separate
+pages, a Draw page, a Show page, and a Blank page.  The Show page refers to
+the page that is currently showing, the Draw page to the page that is
+under construction (to be shown next frame), and the Blank page should always
+be maintained as an up-to-date blank background page.  (The Blank page is
+useful for sprite programming which I am going to be doing next.)  Each
+of the pages is 352x240, although the screen resolution is only 320x200.
+
+  Each frame, the pages rotate DrawPage->ShowPage->BlankPage->DrawPage.
+This means that at the beginning of the frame, the Draw Page is already
+blank, so all that is necessary is to draw on a bunch of sprites.  The
+BlankPage, though, is no longer blank (it's still got stuff from what
+was the ShowPage) so we have to erase it, by blanking out the sprites
+(luckily the new DrawPage _is_ empty, so we can use a Mode X 32-bit video-
+to-video copy to blank it).  Hope you're still with me.
+
+  So, this loop continues with each frame, and the loop invariants are
+maintained:  Show Page is always a "good" frame -- don't touch it.  Blank
+Page is always blank.  Draw Page can look like anything.  Now to include
+the scrolling again:
+
+  The way I do scrolling with several pages is that the pages ALL wander
+around video memory, only they're smaller (1/3 of the size that they could
+have been, to be exact!).  Here's a picture of the situation at its worst:
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ÄÄÄ
+º  ³//ÀÄÄÄÄÄÄÄĺ  ³
+ºÄÄÙ///////////º  ³
+º/////ÚÄÄÄÄÄÄÄĺ  ³
+ºÄÄ¿//³PAGE 0  º  ³
+º  ³//³ (Draw) º  ³
+º  ³//ÀÄÄÄÄÄÄÄĺ  ³
+ºÄÄÙ///////////º 64K
+º/////ÚÄÄÄÄÄÄÄĺ (21K each page)
+ºÄÄ¿//³PAGE 1  º  ³
+º  ³//³ (Show) º  ³
+º  ³//ÀÄÄÄÄÄÄÄĺ  ³
+ºÄÄÙ///////////º  ³
+º/////ÚÄÄÄÄÄÄÄĺ  ³
+ºÄÄ¿//³PAGE 2  º  ³
+º  ³//³ (Blank)º  ³
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ
+The pages always maintain an equal distance apart as they wander.  Since
+all pages move in parallel, the way it used to work is that as soon as the
+pages scrolled, I would draw the newly-visible picture information on
+all three of the pages.  This worked great, except that it resulted in
+a slight pause every time the screen scrolled because it was doing hardware
+pan most of the time (which is very fast) and the drawing routines were
+slow.  Now, I've spread the copying over successive frames to allow a
+smoother scrolling rate.  This is possible because it's not really necessary
+to draw the new information to a page before that page becomes the show
+page...
+
+  I hope that this has made some sense.  It's pretty complicated stuff.
+Take a look at the code and maybe that will help.  Or, write me mail
+(my email address is below).  Or, design your own way and ignore this
+whole thing.
+
+COMING SOON:
+
+  Next up are Sprite routines.  I threw in what I started as SPRITE.INC,
+although it's not included in the project right now.
+  Sound support
+
+  Who knows what else?  Depends on what people send me!
+
+-------------------------------------------------------------------------
+                           R E A D   T H I S
+-------------------------------------------------------------------------
+                           R E A D   T H I S
+-------------------------------------------------------------------------
+
+  This code is being released as "SwapWare".  That means that if you wanted
+to go ahead and use my code directly, I really wouldn't care.  But I ask
+that you send me some of your code that you think is neat.  Especially if
+it's modifications that you make to this code, such as quick sprite drawing
+or optimizations.
+
+  I'm not going to brag and say that I "threw this together in a few hours".
+I didn't, it took me many days of work to get it working properly.  But
+I'm also not looking for money as recompensation for my labor.  I make
+great money at my real day job and you probably have a better use for your
+donations, such as legitimizing your unregistered shareware and pirated
+games.  I'm in this for the knowledge ... so my best payback would be to
+get lots of code from people out there, stuff to really help make a great
+game.  In particular, these would be great:
+        * 32-bit code
+        * Tricky optimizations
+        * Fast BitBlt/masked BitBlt code
+        * Useful File I/O functions
+        * 3D polygon and texture mapping code
+        * Maintenance routines -- like numeric conversions, etc.
+        * Hardware access code like timing routines and interrupt
+          handlers
+Any of those would be very helpful when writing a fast scrolling game.
+
+You can contact me (for the rest of this term only) at
+        seisner@athena.mit.edu
+Feel free to ask any questions you want!  I check my mail about once or
+twice a week so don't expect instant turnaround...  If you're desperate
+to talk to me, say if you work at Origin and want to give me the source
+code to Strike Commander or whatnot, you can also reach me at:
+        Steve Eisner
+        (617) 247-8691
+and leave a message.  But I'd rather you wrote e-mail.
+
+                                        Thanks,
+                                           Steve Eisner
+
+*  Read rec.games.programmer!   And for those who already do:
+   I dream of a world where no one argues over why Wolfenstein
+   3-D sucks or why it doesn't.  Would people just give it a
+   break?
+
\ No newline at end of file
diff --git a/16/scrasm/SCROLL.EXE b/16/scrasm/SCROLL.EXE
new file mode 100644
index 0000000000000000000000000000000000000000..8181acf10f9d8d572a19b978175493810c0e29c9
GIT binary patch
literal 33596
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
Lze7_yL8<=(g0?ev

literal 0
HcmV?d00001

diff --git a/16/scrasm/SCROLL.INC b/16/scrasm/SCROLL.INC
new file mode 100644
index 00000000..be58c025
--- /dev/null
+++ b/16/scrasm/SCROLL.INC
@@ -0,0 +1,441 @@
+;; Global variables used here ...
+EVEN
+ScrollPosX      dw      0       ; Scroll origin, upper-left X
+ScrollPosY      dw      0       ; Scroll origin, upper-left Y
+ScrollDX        dw      0       ; Amount to change scroll origin, X
+ScrollDY        dw      0       ; Amount to change scroll origin, Y
+
+;; SCROLL:
+;; This routine takes care of all of the scrolling, however it calls
+;; outside drawing routines to update the screen.  Scrollx and
+;; Scrolly determine the amount to scroll by.
+;; Note that this does only RELATIVE scrolling, not absolute scrolling.
+;; Scroll saves time by updating only up to the one row or column of
+;; tiles which have come into view due to a change in scroll offset.
+;; In other words, it's not good for "jumping" to a particular point,
+;; although this effect can be accomplished in other ways -- the draw_full
+;; routine is available to draw a full screen again.
+;; Sometimes this means that you will have to calculate values ahead of
+;; time, for instance if you wish the scrolling to keep a certain sprite
+;; in the center of the screen.  In this case, just set ScrollDX and
+;; ScrollDY to the delta-x and delta-y of the sprite.
+;; * Newly added:
+;; Since there are three pages, it is necessary to keep each one of them
+;; up to date with each scroll.  Recently, I was doing some fast (8+
+;; pixels per frame) scrolling and noticed that there was a significant
+;; pause when the screen snapped to a new origin.  (The origin is always
+;; at a square's corner, even though it may not look like it because it
+;; disguises things by smooth-panning the hardware.)  Every time it
+;; scrolled, it was drawing the new information and copying it to the
+;; two other planes.  I've now distributed the load over successive
+;; pages, in other words it doesn't copy the new info all at once, but
+;; over several frames.  This really smoothed out the scrolling so that
+;; while there are still some jumps, they only occur very infrequently
+;; and then only at 15 or 16 pixel/frame scroll rates...)  That's the
+;; "catchup" code at the bottom, and that's why it's more complex than
+;; it maybe could be...
+EVEN
+Scroll          PROC    near
+        ; Using the ScrollDX variable as delta-x, move the scroll-origin
+        ; in the x direction.  Then, if the visible screen is now
+        ; viewing invalid data, snap the origin to a new point and
+        ; draw any new columns that are necessary.
+do_x_scroll:    mov     ax,cs:ScrollPosX
+                add     ax,cs:ScrollDX           ; ScrollDX is a delta-x
+                jl      wrap_l                  ; wrap left if negative
+                cmp     ax,VIRTUAL_WIDTH - SCREEN_WIDTH ; too far right?
+                jge     wrap_r                  ; wrap right if too big
+                mov     cs:ScrollPosX,ax        ; Stores new scroll-x
+        ; (just like above, for y:)
+        ; Using the ScrollDY variable as delta-y, move the scroll-origin
+        ; in the y direction.  Then, if the visible screen is now
+        ; viewing invalid data, snap the origin to a new point and
+        ; draw any new rows that are necessary.
+do_y_scroll:    mov     ax,cs:ScrollPosY
+                add     ax,cs:ScrollDY          ; ScrollDY is a delta-y
+                jl      wrap_t                  ; wrap top if negative
+                cmp     ax,(VIRTUAL_HEIGHT - SCREEN_HEIGHT) * VIRTUAL_WIDTH
+                jge     wrap_b                  ; wrap bottom if too big
+                mov     cs:ScrollPosY,ax        ; Store the new scroll-y
+                jmp     calculate
+
+        ; To wrap to the right:
+        ; Add a square's width to the origin's upper left corner, and
+        ; subtract the same amount from the scroll origin's upper left
+        ; corner.  This makes no difference on the screen but allows
+        ; us to forget about the leftmost column on the screen (it's
+        ; offscreen now...) so we can take over the right column.
+        ; See any documentation I included for an explanation of the
+EVEN    ; scrolling...
+wrap_r:         add     cs:upper_left,SQUARE_WIDTH / 4
+                sub     ax,SQUARE_WIDTH
+                mov     cs:ScrollPosX,ax
+
+                mov     dx,MapInfo.Wid
+                mov     bp,MapInfo.OffX1
+                inc     bp
+                cmp     bp,dx
+                jb      wrap_r1_ok
+                sub     bp,dx
+wrap_r1_ok:     mov     MapInfo.OffX1,bp
+
+                mov     bp,MapInfo.OffX2
+                inc     bp
+                cmp     bp,dx
+                jb      wrap_r2_ok
+                sub     bp,dx
+wrap_r2_ok:     mov     MapInfo.OffX2,bp
+
+                mov     bp,MapInfo.WrapX
+                dec     bp
+                jnz     wrap_r3_ok
+                add     bp,dx
+wrap_r3_ok:     mov     MapInfo.WrapX,bp
+
+                call    update_right
+                jmp     do_y_scroll     ; Jump back to do Y
+
+EVEN    ; Same for left side
+wrap_l:         sub     cs:upper_left,SQUARE_WIDTH / 4
+                add     ax,SQUARE_WIDTH
+                mov     cs:ScrollPosX,ax
+
+                mov     dx,MapInfo.Wid
+                mov     bp,MapInfo.OffX1
+                dec     bp
+                cmp     bp,dx
+                jb      wrap_l1_ok
+                add     bp,dx
+wrap_l1_ok:     mov     MapInfo.OffX1,bp
+
+                mov     bp,MapInfo.OffX2
+                dec     bp
+                cmp     bp,dx
+                jb      wrap_l2_ok
+                add     bp,dx
+wrap_l2_ok:     mov     MapInfo.OffX2,bp
+
+                mov     bp,MapInfo.WrapX
+                inc     bp
+                cmp     bp,dx
+                jbe     wrap_l3_ok
+                sub     bp,dx
+wrap_l3_ok:     mov     MapInfo.WrapX,bp
+
+                call    update_left
+                jmp     do_y_scroll     ; Jump back to do Y
+
+EVEN    ; Same for bottom
+wrap_b:         add     cs:upper_left,(SQUARE_HEIGHT * VIRTUAL_WIDTH) / 4
+                sub     ax,SQUARE_HEIGHT * VIRTUAL_WIDTH
+                mov     cs:ScrollPosY,ax
+
+                mov     bp,MapInfo.OffY1
+                mov     dx,MapInfo.Extent
+                add     bp,MapInfo.Wid
+                cmp     bp,dx
+                jb      wrap_b1_ok
+                sub     bp,dx
+wrap_b1_ok:     mov     MapInfo.OffY1,bp
+
+                mov     bp,MapInfo.OffY2
+                add     bp,MapInfo.Wid
+                cmp     bp,dx
+                jb      wrap_b2_ok
+                sub     bp,dx
+wrap_b2_ok:     mov     MapInfo.OffY2,bp
+
+                mov     dx,MapInfo.Ht
+                mov     bp,MapInfo.WrapY
+                dec     bp
+                jg      wrap_b3_ok
+                add     bp,dx
+wrap_b3_ok:     mov     MapInfo.WrapY,bp
+
+                call    update_bottom
+                mov     ax,cs:ScrollPosY
+                jmp     calculate       ; Jump down to calc new offsets
+
+EVEN    ; Same for top
+wrap_t:         sub     cs:upper_left,(SQUARE_HEIGHT * VIRTUAL_WIDTH) / 4
+                add     ax,SQUARE_HEIGHT * VIRTUAL_WIDTH
+                mov     cs:ScrollPosY,ax
+
+                mov     bp,MapInfo.OffY1
+                mov     dx,MapInfo.Extent
+                sub     bp,MapInfo.Wid
+                cmp     bp,dx
+                jb      wrap_t1_ok
+                add     bp,dx
+wrap_t1_ok:     mov     MapInfo.OffY1,bp
+
+                mov     bp,MapInfo.OffY2
+                sub     bp,MapInfo.Wid
+                cmp     bp,dx
+                jb      wrap_t2_ok
+                add     bp,dx
+wrap_t2_ok:     mov     MapInfo.OffY2,bp
+
+                mov     bp,MapInfo.WrapY
+                mov     dx,MapInfo.Ht
+                inc     bp
+                cmp     bp,dx
+                jbe     wrap_t3_ok
+                sub     bp,dx
+wrap_t3_ok:     mov     MapInfo.WrapY,bp
+
+                call    update_top
+                mov     ax,cs:ScrollPosY
+                jmp     calculate       ; Jump down to calc new offsets
+
+EVEN
+align_mask_table DB     11h,22h,44h,88h
+calculate:
+        ; Calculate the scroll offset
+        ; AX already = ScrollPosY
+                add     ax,cs:ScrollPosX        ;Now AX = scroll offset
+
+        ; Calculate the plane alignment
+                mov     bl,al
+                and     bx,0003h
+                mov     cs:DrawPage.Alignment,bl
+;               mov     bl,cs:align_mask_table[bx]
+;               mov     cs:DrawPage.AlignmentMask,bl
+
+        ; Now we don't need Scroll Offset on a pixel level any more,
+        ; so shift it to a byte level (/4) and store it away.
+                shr     ax,2
+                mov     cs:DrawPage.ScrollOffset,ax
+
+        ; Calculate the actual upper left corner address
+                mov     si,cs:DrawPage.Address
+                add     si,cs:upper_left
+                mov     cs:DrawPage.UpperLeftAddress,si
+
+        ; And the map offset:
+                mov     bx,MapInfo.WrapX
+                mov     cs:DrawPage.MapPosX,bx
+                mov     di,MapInfo.WrapY
+                mov     cs:DrawPage.MapPosY,di
+
+                mov     cs:DrawPage.Valid,1
+                cmp     cs:BlankPage.Valid,0
+                je      no_catch_up
+
+        ; Lastly, update dirty area (if any) on blank page.
+        ; BP still contains the draw page's mapoffset.
+                sub     bx,cs:BlankPage.MapPosX
+                sub     di,cs:BlankPage.MapPosY
+                jnz     yes_catch_up
+                cmp     bx,0
+                jnz     yes_catch_up
+        ; No catchup necessary -- return.
+no_catch_up:    ret
+
+;; Okay, this stuff is a mess.  I've registerized everything except
+;; for the video data itself.  I'll try to comment it best I can.
+EVEN
+yes_catch_up:
+        ; First, switch into full-copy mode.  This means latching the
+        ; bit mask as coming entirely from the local 32-bit registers
+        ; and then setting the map mask to write to all 4 planes.  This
+        ; is Mode X's greatest advantage, when you can do it!  It
+        ; provides a 2x speedup or so...
+                mov     dx,SC_INDEX     ; Select Sequencer input
+                mov     ax,0F02h
+                out     dx,ax           ; set map mask = all bits
+
+                mov     dx,GC_INDEX
+                mov     ax,ALL_COPY_BITS
+                out     dx,ax
+
+                JKEYNP  kB,isntbp
+isbp:           nop
+isntbp:
+        ; Next, calculate the amount to catch up the top/bottom rows
+        ; If we just wrapped over the edge, it is possible that the
+        ; distance traveled will be as high as MapInfo.Ht - 1.  So,
+        ; in the fashion of signed numbers, if the number is greater
+        ; than MapInfo.Ht / 2, we take it to mean negative.  To convert
+        ; it to signed, we have to shift it into the proper range.  But
+        ; if it's less than MapInfo.Ht / 2, then it's okay as it is.
+                mov     ax,di
+                cmp     ax,0
+                je      y_mod
+
+                mov     cx,MapInfo.Ht
+                cwd             ; DX = -1 or 0 based on AX's sign.
+                and     dx,cx   ; DX = Ht or 0
+                add     ax,dx   ; AX = 0 ... Ht (unsigned)
+
+                mov     di,ax
+                shl     di,1
+                cmp     di,cx
+                jb      y_signed
+                sub     ax,cx
+y_signed:       neg     ax
+
+        ; Find DI MOD MapInfo.Wid, and then convert to it into virtual
+        ; coordinates from map offset coordinates.
+        ; This routine also calculates BP, which will be used as a loop
+        ; counter to determine how many rows to draw on the left/right
+        ; column copy.
+y_mod:          mov     bp,ax
+                cwd
+                add     bp,dx
+                xor     bp,dx
+                shl     bp,3            ; BP = (SQUARE_HEIGHT / 2) * dX
+                mov     di,cs:MultVirtWidth[bp] ; Use multiplication table
+                add     di,dx                   ; to calculate new DI, then
+                xor     di,dx                   ; restore the sign.
+                sub     bp,VIRTUAL_HEIGHT / 2
+        ; Out:  DI = # of pixels traveled,
+        ;       BP = (VIRTUAL_HEIGHT - # of rows) / 2
+
+        ; Change BX (delta-x) to signed from unsigned, store in AX
+                mov     ax,bx
+                mov     cx,MapInfo.Wid
+                cwd
+                and     dx,cx   ; DX = Wid or 0
+                add     ax,dx   ; AX = 0 ... Wid
+
+                mov     bx,ax
+                shl     bx,1
+                cmp     bx,cx
+                jb      x_signed
+                sub     ax,cx
+x_signed:
+
+        ; The following is an optimization which would slow down on
+        ; normal memory, but I believe it will be okay on VGA memory,
+        ; which is so incredibly slow.  Basically, I've replaced all
+        ; "rep movsb"'s with a loop that first calculates "bx = di - si",
+        ; and then loops performing "mov ds:[si],es:[si+bx]".  Why?
+        ; Because of several reasons, none of which I'm sure actually
+        ; help out, but they do make for smaller code.  1)  It means that
+        ; I only have to maintain SI, and "DI" is maintained automatically
+        ; (because DI - SI should remain constant).  2)  Don't have to
+        ; calculate DS.  Not much gain here.  3)  Because I'd already
+        ; unrolled the loops, and the "rep movsb"'s had become instead
+        ; "mov al, ds:[si] / mov es:[di], al / mov al, ds:[si + 1] /
+        ; mov es:[di + 1],al ... etc ... add si, 4 / add di, 4".  In
+        ; other words, I wasn't using MOVSB anyway.  The only advantage
+        ; I can see in MOVSB is that it doesn't have to store the answer
+        ; in AL so it could be slightly faster.  By unrolling the loops,
+        ; I'd already made up for that, I think.  4)  Normally, using
+        ; [SI + BX + 1] would incur a penalty of an additional clock
+        ; cycle (because it has to add two indexs + an offset).  But
+        ; the VGA memory and the '86 CPU can multi-task, and the VGA
+        ; is very slow.  So by the time the VGA is ready to write the
+        ; next byte, the one extra clock cycle has already passed.
+        ;
+        ; Am I right?  Does this make things faster?  I have no idea.
+        ; I haven't bothered to check both ways.  Please let me know
+        ; if I've missed something important...
+        ;
+        ; Here's the calculation of BX.  SI is already set.
+                ; si already = DrawPage.UpperLeftAddress
+                mov     bx,cs:BlankPage.Address
+                sub     bx,cs:DrawPage.Address
+
+        ; Now, converts SI into "1/4" units.  I do all the calculations
+        ; in "1/4" scale and then scale back up, mostly because it saved
+        ; me some instructions elsewhere.
+                shr     si,2
+        ; Stores this value of SI.  This will be restored after doing
+        ; the top/bottom copying.
+                mov     dx,si
+
+        ; Check if it's necessary to catch up the top or bottom.
+catchup_tb:     cmp     di,0
+                je      catchup_tb_end
+                jl      catchup_t
+catchup_b:      ; COPY BOTTOM
+        ; Move SI to point at the bottom of the screen - # of rows
+        ; to update.
+                add     si,((VIRTUAL_WIDTH * VIRTUAL_HEIGHT) / 4) / 4
+                sub     si,di
+                jmp     copy_tb
+catchup_t:      ; COPY_TOP
+        ; Leave SI, but add to the "pushed" value of SI the number of
+        ; rows that will be drawn.  This prevents overlap between top
+        ; and right/left when moving diagonally.  Also, DI = |DI|
+                neg     di
+                add     dx,di
+
+        ; Now do the actual copying.  Shifts SI back into scale "1",
+        ; then performs an unrolled loop to copy the entire virtual
+        ; width * # of pixel rows.  Since DI is already in "1/4" scale,
+        ; it is only decremented once for each four pixels drawn.
+copy_tb:        shl     si,2
+copy_tb_loop:   mov     cl,es:[si]
+                mov     es:[si+bx],cl
+                mov     cl,es:[si+1]
+                mov     es:[si+bx+1],cl
+                mov     cl,es:[si+2]
+                mov     es:[si+bx+2],cl
+                mov     cl,es:[si+3]
+                mov     es:[si+bx+3],cl
+                add     si,4
+                dec     di
+                jnz     copy_tb_loop
+catchup_tb_end:
+
+        ; Next, check to see if it's necessary to draw the right or
+        ; the left side.
+catchup_rl:     cmp     ax,0
+                je      catchup_rl_end
+                jg      catchup_l
+catchup_r:      ; COPY RIGHT
+        ; Adds to the "pushed" SI the width of the screen, minus
+        ; the number of rows to be drawn.
+                neg     ax
+                add     dx,(VIRTUAL_WIDTH / 4) / 4
+                sub     dx,ax
+catchup_l:      ; COPY LEFT (or nothing)
+
+        ; Does the actual copying.  First pops SI from its stored value
+        ; and shifts it back into scale "1"
+copy_rl:        mov     si,dx
+                shl     si,2
+
+        ; This is a loop over BP -- which has already been set as
+        ; VIRTUAL_HEIGHT - (# of bytes drawn in vertical update)
+        ; Again, this loop is unrolled such that it does two rows @
+        ; 4 bytes each with every iteration.
+        ; This LEA instruction is just a quick MOV DI, SI + 2 *y
+        ; DI is used to push the next value of SI for each iteration
+        ; of the loop.
+copy_rl_loop:   lea     di,[si + 2*(VIRTUAL_WIDTH/4)]
+                mov     cx,ax
+copy_rl_col:    mov     dl,es:[si]
+                mov     es:[si+bx],dl
+                mov     dl,es:[si+1]
+                mov     es:[si+bx+1],dl
+                mov     dl,es:[si+2]
+                mov     es:[si+bx+2],dl
+                mov     dl,es:[si+3]
+                mov     es:[si+bx+3],dl
+                mov     dl,es:[si+VIRTUAL_WIDTH/4]
+                mov     es:[si+bx+VIRTUAL_WIDTH/4],dl
+                mov     dl,es:[si+VIRTUAL_WIDTH/4+1]
+                mov     es:[si+bx+VIRTUAL_WIDTH/4+1],dl
+                mov     dl,es:[si+VIRTUAL_WIDTH/4+2]
+                mov     es:[si+bx+VIRTUAL_WIDTH/4+2],dl
+                mov     dl,es:[si+VIRTUAL_WIDTH/4+3]
+                mov     es:[si+bx+VIRTUAL_WIDTH/4+3],dl
+                add     si,4
+                dec     cx
+                jnz     copy_rl_col
+                mov     si,di           ; SI = pop (SI + VIRTUAL_WIDTH/4)
+                inc     bp              ; (BP is negative, so INC it)
+                jnz     copy_rl_loop
+catchup_rl_end:
+
+        ; Switch back to all-draw mode.
+                mov     dx,GC_INDEX
+                mov     ax,ALL_DRAW_BITS
+                out     dx,ax
+                ret
+Scroll          ENDP
+
\ No newline at end of file
diff --git a/16/scrasm/SCROLL.LNK b/16/scrasm/SCROLL.LNK
new file mode 100644
index 00000000..275ba401
--- /dev/null
+++ b/16/scrasm/SCROLL.LNK
@@ -0,0 +1,2 @@
+main.obj+lztimer.obj  
+scroll; 
diff --git a/16/scrasm/SCROLL.MAP b/16/scrasm/SCROLL.MAP
new file mode 100644
index 0000000000000000000000000000000000000000..0b18f2bfd53fc0be47f22d8f609a476a270c1ee1
GIT binary patch
literal 344
zcmbV{T?)c55QL|7+xU}Mt*zDguhA3u-~qfyK@dUo{!ewcRj8sbE(|kYW?9JblArIl
z{0dtX78(Z+JSp}NIthFq2hVSmN_@j^kPJ}Dfm$6<pOsqBxC!D$<Pa%Sk(z+AdZXJ+
zJq;R8L8E78=4*;cB>S(-{$CS>T|{AwAdA_nEbQLDIm3LhT&*|!`q9+(-1gV(9&^$W
A(f|Me

literal 0
HcmV?d00001

diff --git a/16/scrasm/SCROLL.PAL b/16/scrasm/SCROLL.PAL
new file mode 100644
index 0000000000000000000000000000000000000000..5dee1969fc3e9dfe5bee855460c512ba3a850e69
GIT binary patch
literal 768
zcmWO4fugA}007W2rBcR}O4&6{OBqvI%Gm$^)qCd~4gg>dt%dE`E^_?PL#dC+Ix03v
zg)<S7c29?d=>s=;JrU8Lq&#;GQ)M~QO6RqSZwB9WAV;TF@YMk&t+()|8fhN>SZXNw
zlH!w9V<LvA?eWkd{q)VlorK*tP+md9L3x3+uyg9he?C5<Aj3`?!8id?X6=Z#r3kSw
z;OVL+t|*qWvN{1(I~xa}_1u_+nQYxVqx4kccja2rjmU8whaB%&kWlA9V4eYzSf|K4
zW5iHc`f25o+AeOex&t9W+rr^xYvr1^KTW9DSpK5MB;_}wACiwW9vJR<(ACaUz=s5)
zvl``HN5pk_F==54)y3af9hJzsHkCsxbX1!ipSG+=R0gD3Wu=?YWt3Yuh6vC60JzTF
zh6@O6U^&3^AoA^S?WP-_U{r*-+D9Tu+Cw(vL=$RGY&!Fv)v^>#CCj>_H<jPVSZdsw
z;AI@8;d=y=vUKPDBr+oW*6D|nkre~2dLp{4eI~;r(gK?XO;^9?uDsYy0ZR(#AIOg|
z&TO2zLF_vbf;$Yhk%ba3$k2*}E=`w=SiFFBH4_5JcHRvOrR~u;dh$%~8@blaW-PIy
zVVCb^oCtiVgPc2r!4m~%VzJCC6I4ZEjnf+<cfXKs)!O0(TLp$U&=WM;o_=m`eECJq
z2bW{?KVsfzaYyiz1`p;44x1WWg~g?J=}@6UI;MY`98Hm#D%Bz$+ei(&PH&|_VhZYh
R#ih%dB`qyNVV2L5_#e4jUwr@o

literal 0
HcmV?d00001

diff --git a/16/scrasm/SCROLL.TIL b/16/scrasm/SCROLL.TIL
new file mode 100644
index 0000000000000000000000000000000000000000..3b47a8e16873aff2b8cfc2bb04cbd1e44b8e4db0
GIT binary patch
literal 9984
zcmeH}>vpR+3`YH{A-DDwc&TZ^J$?U|nElC!m;^{jyVjYmIcim7<1NXuY#PG<UOqzj
z$V13;nw(}*d6iEo*^B%Ho6ZNH6ma;lZ|5d~n?d6f-(uIu2eM}V?cBfoe<FWgGOOFw
z00odTxApMb`srF$KmR>DO4-Zu+wYE-7ycLg$qcMMwm451?r(j8`H-i|kUs2#rtj?8
zzS_F`$GkJ3Bk}Q^QB&u2hxB8b^GGx&cNN?7&#-QLu%QFE&i%-Q*o0SD&xDb>SN7nB
z6u6BkI~p5UF=8ip*+}i&aGpNr_5auFq6EH9vx+~=|K`|#B6sn>?~lNp;HtafY3cua
z4^$#LvhkE1D`@`Q@NP>sTzR~gD?e)^KuO)sZOf~tMQn)rLG8-tQ{p}~A62eY`-{9Y
ziO;KVOvKAzeqFsUXS|KRoll*l&ogk&wL|0<J*|4vvS`a}*qt}ar&iroV9?a~n89@3
zqi5MMUai@Pmyc@bR<*cEwLMb?tlou9N@_1>#z@V^GM^fCTZ0YbEe5@MS~NL#H5>YR
z=v-WDVtDWK`c~|e4!rCwFua-+eA`YC!oa(qN#JJC_#5_S%3_!JUl!fJFT;R8#P@rs
zeO#yV@40@pT}<vTcxgFUo49m72I#&l^8Ydn_yfEhJ@$W1E!d|^p-b6jSC!Et(VScw
z`JCrF8&h^PHn3upIq3~g-|YK*Z+*OPuRLFJ&w<)Cd0?{q-^JiQ31wNd`MA%YSi_{D
zD?e)k+d=9vjoMLXZqmXyul}@rYYET7Ijc-m1*6lap{K<C<Z+`x*YP+p6a3LeqwKuZ
z&Gf$d{G<hoONcfiZ${$hfASD|+;eThE3V<};Oi;T8f-1ZrnrFI)hfPc#k;zl#TM^>
zQndQDBE~f&&p!636_YAm6XyawwEv&b+F`!WF`)nBV=%)!p5e7AW8UXDqt?fgw)buP
ztc_%TYQy7(8~8;VgzzoV8ona|IL*geTjEnqZ9ROxJ7j#6!~6Stct5^};~@lo!yeuB
zdIyXLbl9N7@rd$s*zdz0-R)2_GM<0iGhQ~(LpU7w{EZf#<aGln02F>?UQ1XM{t>{j
zTob*5kIs2k2DTwH-S9ju<c`$6M;OTS*0<X%glwMX^1R{kVm6}pkZs|oJ=^Fwd<B2#
za~=cG0yaw)v~sD7$M1dN`k4`1J9WdpYv1<l`3~7`gEZT2VBg+mV1~t$JxWLWzTZ<X
zyIt6tZo_uF$+ED>V?()j>C@(2Tl*#~1mMNzgbYYsl>FJ%$B&<t9@7-Zf%0P!R`qOM
zAp8gWA4}I*@u-KO+9iq0Jaf|R6Q9<+Vps@Yuzs%Yb>v8VZ)OXu^vx!)-#x2;#m$jt
z_pa;TY&O~38&xnP&MR(@-PTP%=5Is&%vV4RUm1uNsG+|8WhJxfUnt-BpT{_XcKHCu
zG(OmW9bj7nmCV^Y9QFqS(8Wgya}Kg>n~{RqBkbp&b-*7fA8t;L5Q&tHZMNkMg!%kk
z%QtReygP}$mq+3EyDvD(js$Xe>0H-8yZiC{a(X$x7Q0^nI{!P$D9czo+qbm;;iwyc
z`-8O~a1W=i1`9WSlTiTkd|$xV@QwAZ-F$c9x8*6c)n{mE8`{`s%=+=&=)LAvn%i@Q
z*ndKeHU%yHx<obJ_x0XXecsu)jeTCKB3$Y-N?UoW=OT2BONaNGgLZny+>Ym#_bt!f
zYFvG9TMP5r?`nk|?Y2C-T)r-suDf(?*L7{vwsl=M{M2<-*JW8%MNyPz$?1GLeSUsA
z=k3?!>q|TagtrX>U03i`S(Rm36z6jR%rD}cw-*yR@45y9313CJEYFw#KjZ(7|N628
zz$<`;_~pK7DgrQG5fFg*&(wdv{}=YZWB=Q>gs<RB*012Je*O4ws`HszI8E&T7yI8e
zMaQ1BO<fW~k*pu*4elG_uglYEdjBu%zj(sHMm6NmA}DI|UyCo!?Eh(E|1a!o$9UIP
atiQrNHf;SQpfEib>_1C5pHx@c|9=5^-};gO

literal 0
HcmV?d00001

diff --git a/16/scrasm/SPRITE.INC b/16/scrasm/SPRITE.INC
new file mode 100644
index 00000000..9c3f2e48
--- /dev/null
+++ b/16/scrasm/SPRITE.INC
@@ -0,0 +1,280 @@
+; SPRITE routines
+MAX_SPRITE      EQU     100
+
+RECTANGLE STRUCT 2,NONUNIQUE
+                X       WORD    0
+                Y       WORD    0
+                Wid4    BYTE    0
+                Ht      BYTE    0
+                Color   BYTE    0
+                Next    WORD    0
+        ; DrawMe is used to not bother with sprites that you know
+        ; are contained totally within another, allowing animated
+        ; eyes, etc to be stored in separate sprites.  These will be
+        ; drawn to the local buffer but skipped when copying to the
+        ; screen, so if they are not TOTALLY contained, they will
+        ; just get clipped away.
+                DrawMe  BYTE    1       ; default, yes draw me.
+        ; (Storage from this point on ... NEVER provide anything but
+        ; default for these values!)
+                address_virt    WORD    0
+                address_buf     WORD    0
+                next_line_virt  WORD    0
+                next_line_buf   WORD    0
+RECTANGLE ENDS
+
+SPRITE  STRUCT 2, NONUNIQUE
+        RECTANGLE       <>      ; Contains rectangle info
+SPRITE  ENDS
+
+EVEN
+rect5   SPRITE  <<40 ,60 , 2,8, C_TRANSPARENT, 0           , 0>>
+rect4   SPRITE  <<80 ,30 , 2,8, C_TRANSPARENT, offset rect5, 0>>
+rect3   SPRITE  <<120,60 , 2,8, C_TRANSPARENT, offset rect4, 0>>
+rect2   SPRITE  <<55 ,100, 2,8, C_TRANSPARENT, offset rect3, 0>>
+rect1   SPRITE  <<105,100, 2,8, C_TRANSPARENT, offset rect2, 0>>
+
+rect6   SPRITE  <<36 ,56 , 4,16, C_BLUE, offset rect1, 1>>
+rect7   SPRITE  <<76 ,26 , 4,16, C_BLUE, offset rect6, 1>>
+rect8   SPRITE  <<116,56 , 4,16, C_BLUE, offset rect7, 1>>
+rect9   SPRITE  <<51 ,96 , 4,16, C_BLUE, offset rect8, 1>>
+rect10  SPRITE  <<101,96 , 4,16, C_BLUE, offset rect9, 1>>
+
+;; Simply adding in these 5 rectangles (~20000 pixels for both
+;; drawing and erasing) really slows things down!  That's why
+;; it's important to optimize the sprite drawing routines!
+rect11  SPRITE  <<35 ,55 ,14,36, C_GREEN, offset rect10, 1>>
+rect12  SPRITE  <<75 ,25 ,14,36, C_GREEN, offset rect11, 1>>
+rect13  SPRITE  <<115,55 ,14,36, C_GREEN, offset rect12, 1>>
+rect14  SPRITE  <<50 ,95 ,14,36, C_GREEN, offset rect13, 1>>
+rect15  SPRITE  <<100,95 ,14,36, C_GREEN, offset rect14, 1>>
+
+FIRST_SPRITE    EQU     rect10
+
+EVEN
+AnimateSprites  PROC    near
+                ret
+        ; Blank out the draw page, by copying from the blank page
+        ; to the draw page all rectangles which had changed.  The
+        ; blank page must always be entirely blank if this is going
+        ; to work!
+                mov     di,cs:DrawPage.UpperLeftAddress
+                add     di,cs:DrawPage.ScrollOffset
+                mov     si,cs:BlankPage.UpperLeftAddress
+                add     si,cs:BlankPage.ScrollOffset
+                mov     bp,cs:BlankPage.Rectangles
+                call    CopyRectangles
+
+        ; Now draw the sprites.  Uses a temporary buffer to ensure
+        ; minimal drawing to the screen, but that's not really necessary,
+        ; if memory is at a minimum.  It's just faster...
+                mov     bp,offset FIRST_SPRITE
+                mov     cs:DrawPage.Rectangles,bp
+                call    do_fill_buffer
+                mov     di,cs:DrawPage.UpperLeftAddress
+                add     di,cs:DrawPage.ScrollOffset
+                mov     bh,cs:DrawPage.AlignmentMask
+                mov     bp,offset FIRST_SPRITE
+                jmp     smart_rects     ; "call"
+AnimateSprites  ENDP
+
+smart_dest      DW      0
+out_di          DW      0
+out_si          DW      0
+
+EVEN
+smart_rects     PROC    near
+                add     di,cs:DrawPage.Address
+                mov     ds,cs:segBuffer
+                mov     es,cs:segVideo
+                mov     dx,3c4h
+                mov     al,02h
+                out     dx,al
+                inc     dx
+                mov     cs:smart_dest,di
+
+        ; === Beginning of loop through rectangles! ===
+sp_nextrect:
+                cmp     cs:[bp].RECTANGLE.DrawMe,1
+                jne     sp_next
+        ; Draw this rectangle from the buffer to screen memory.
+        ; Calculate the output address.
+                mov     si,cs:[bp].RECTANGLE.address_buf
+                mov     di,cs:[bp].RECTANGLE.address_virt
+                add     di,cs:smart_dest
+
+        ; Loop over 4 planes
+                mov     bl,4
+sp_plane_loop:  mov     al,bh
+                out     dx,al
+
+                mov     cs:out_di,di
+                mov     cs:out_si,si
+
+        ; Loop over height
+                mov     ch,cs:[bp].RECTANGLE.Ht
+sp_row_loop:
+
+        ; Loop over width of rectangle (Wid4 is actually width/4)
+                mov     cl,cs:[bp].RECTANGLE.Wid4
+sp_col_loop:
+
+        ; Read a byte from the buffer
+        ; Is it transparent (no-modify)?  If so, just jump over the draw
+                mov     al,byte ptr ds:[si]
+                cmp     al,C_TRANSPARENT
+                je      sp_next_pixel
+        ; Otherwise, draw it on the spreen, and mark it transparent
+        ; so that it won't be drawn again.
+                mov     byte ptr es:[di],al
+                mov     byte ptr ds:[si],C_TRANSPARENT
+
+        ; Skip to next 4-byte group (next column that can be drawn in
+        ; Mode X)  Also increment spreen draw address, but only by 1
+        ; because ModeX is 4 pixels per byte
+sp_next_pixel:
+                add     si,4
+                inc     di
+
+                dec     cl
+                jnz     sp_col_loop
+
+        ; End of row.  Skip space to get to left edge of next row down
+        ;  Skip SI = (SCREEN_WIDTH - #bytesdrawn)
+        ; Only draw up to height of rectangle
+                add     si,cs:[bp].RECTANGLE.next_line_buf
+                add     di,cs:[bp].RECTANGLE.next_line_virt
+                dec     ch
+                jnz     sp_row_loop
+
+                mov     di,cs:out_di
+                mov     si,cs:out_si
+                inc     si
+                rol     bh,1
+                adc     di,0
+
+                dec     bl
+                jnz     sp_plane_loop
+
+        ; Follow chain to next rectangle
+sp_next:        mov     bp,cs:[bp].RECTANGLE.Next
+                cmp     bp,0
+                jne     sp_nextrect
+        ; All done
+sp_end:         ret
+smart_rects     ENDP
+
+; BP -> first rectangle.  Follows BP->next, stops when BP = 0
+EVEN
+do_fill_buffer  PROC    near
+                mov     es,cs:segBuffer
+
+                cmp     bp,0
+                je      fill_end
+fill_loop:
+
+                mov     bx,cs:[bp].RECTANGLE.Y
+                shl     bx,1                    ; BX = word index y
+                mov     di,cs:MultBufWidth[bx]  ; DI = SW * y
+                mov     cx,cs:[bp].RECTANGLE.X  ; CX = x
+                add     di,cx                   ; DI = (SW * y) + x
+                mov     cs:[bp].RECTANGLE.address_buf,di ; (DI used later)
+
+                mov     ax,cs:MultVirtWidth[bx] ; AX = (VW/4) * y
+                shr     cx,2                    ; CX = (x / 4)
+                add     ax,cx                   ; AX = (VW * y + x)/4
+                mov     cs:[bp].RECTANGLE.address_virt,ax
+
+                mov     dx,(VIRTUAL_WIDTH / 4)
+                sub     dl,cs:[bp].RECTANGLE.Wid4 ; DX = (VW - w) / 4
+                mov     cs:[bp].RECTANGLE.next_line_virt,dx
+
+                mov     dx,(SCREEN_WIDTH / 4)
+                sub     dl,cs:[bp].RECTANGLE.Wid4 ; DX = (SW - w) / 4
+                shl     dx,2                      ; DX = SW - w
+                mov     cs:[bp].RECTANGLE.next_line_buf,dx
+
+                mov     ah,cs:[bp].RECTANGLE.Color
+                mov     al,cs:[bp].RECTANGLE.Color
+
+                mov     ch,cs:[bp].RECTANGLE.Ht
+fill_row_loop:  mov     cl,cs:[bp].RECTANGLE.Wid4
+fill_col_loop:  mov     es:[di],ax
+                mov     es:[di+2],ax
+                add     di,4
+                dec     cl
+                jnz     fill_col_loop
+                add     di,dx
+                dec     ch
+                jnz     fill_row_loop
+
+                mov     bp,cs:[bp].RECTANGLE.Next
+                cmp     bp,0
+                jne     fill_loop
+fill_end:       ret
+do_fill_buffer  ENDP
+
+EVEN
+CopyRectangles  PROC    near
+                mov     ax,cs:segVideo
+                mov     ds,ax
+                mov     es,ax
+
+        ; Calculate the difference between the source and destination
+        ; pages.  Since in a movsb loop the two would remain a constant
+        ; distance apart, we can just calculate a displacement and then
+        ; not have to worry about SI; instead use DI and DI+BX, thanks
+        ; to the thoughtful x86 ALU!
+                mov     bx,di
+                sub     bx,si
+
+                mov     dx,GC_INDEX
+                mov     ax,ALL_COPY_BITS
+                out     dx,ax
+
+                mov     dx,SC_INDEX
+                mov     ax,0F02h
+                out     dx,ax
+                mov     si,di   ;store destination
+
+        ; === Beginning of loop through rectangles! ===
+cr_nextrect:    cmp     cs:[bp].RECTANGLE.DrawMe,1
+                jne     cr_next
+        ; Draw this rectangle from the buffer to screen memory.
+        ; Calculate the output address.
+                mov     di,cs:[bp].RECTANGLE.address_virt
+                mov     dx,cs:[bp].RECTANGLE.next_line_virt
+                add     di,si
+
+        ; Loop over height
+                mov     ch,cs:[bp].RECTANGLE.Ht
+cr_row_loop:
+
+        ; Loop over width of rectangle (Wid4 is actually width/4)
+                mov     cl,cs:[bp].RECTANGLE.Wid4
+cr_col_loop:    mov     al,ds:[di + bx]
+                stosb
+                dec     cl
+                jnz     cr_col_loop
+                mov     al,ds:[di + bx]
+                mov     es:[di],al
+
+        ; End of row.  Skip space to get to left edge of next row down
+        ; Only draw up to height of rectangle
+                add     di,dx
+                dec     ch
+                jnz     cr_row_loop
+
+        ; Follow chain to next rectangle
+cr_next:        mov     bp,cs:[bp].RECTANGLE.Next
+                cmp     bp,0
+                jne     cr_nextrect
+        ; All done
+cr_end:
+                mov     dx,GC_INDEX
+                mov     ax,ALL_DRAW_BITS
+                out     dx,ax
+                ret
+CopyRectangles  ENDP
+
+
\ No newline at end of file
-- 
2.39.5